代码之家  ›  专栏  ›  技术社区  ›  Weknin

将JsObject保存到DynamoDB中

  •  0
  • Weknin  · 技术社区  · 7 年前

    我们希望将数据模型保存到DynamoDB中。我们使用scanamo和alpakka实现非阻塞I/O。 出于多种原因,我们不希望密钥和数据自动生成为dynamo格式。我们已经为所有case类提供了Play-Json格式化程序,并希望数据从JsObjects保存到Dynamo中。

    为了将数据保存为JsObject,每个存储库都有以下内容

    import com.gu.scanamo.Table
    val table = Table[JsObject](name)
    

    始终收到此错误:

    找不到com类型的证据参数的隐式值。顾。斯堪那摩。DynamoFormat[play.api.libs.json.JsObject]

    我找不到一种方法让它接受JsObject或创建一个合适的格式化程序。 非常感谢您的帮助。

    旁注:我已经看过 PlayDynamo-Repo 但他们实际上从头开始创建整个请求,我们希望使用scanamo的API。

    1 回复  |  直到 7 年前
        1
  •  0
  •   Weknin    7 年前

    我最终使用了以下代码,其工作原理与预期一样。我不能分享子功能,但它应该给出总体思路。

    implicit val dynamoFormat: DynamoFormat[JsValue] = new DynamoFormat[JsValue] {
        override def read(av: AttributeValue): Either[DynamoReadError, JsValue] = {
            Option(av.getS).map {
                fromStringAttributeValue
            } orElse Option(av.getN).map { n =>
                Right(JsNumber(BigDecimal.apply(n)))
            } orElse Option(av.getBOOL).map { b =>
                Right(JsBoolean(b))
            } orElse Option(av.isNULL).map { _ =>
                Right(JsNull)
            } orElse Option(av.getSS).map { ss =>
                Right(JsArray(ss.asScala.map(JsString.apply)))
            } orElse Option(av.getNS).map { ns =>
                Right(JsArray(ns.asScala.map(n => JsNumber(BigDecimal(n)))))
            } orElse Option(av.getL).map { l =>
                traverse(l.asScala.toList)(read).right.map(JsArray.apply)
            } orElse Option(av.getM).map { m =>
                traverse(m.asScala) {
                    case (k, v) => read(v).right.map(j => k -> j)
                }.right.map(values => JsObject(values.toMap))
            } getOrElse {
                Left(YOUR_ERROR_HERE)
            }
        }
    
        override def write(t: JsValue): AttributeValue = {
            val res = new AttributeValue()
            t match {
                case JsNumber(n) => res.setN(n.toString())
                case JsBoolean(b) => res.setBOOL(b)
                case JsString(s) => res.setS(stringToAttributeValueString(s))
                case a: JsArray => res.setL(a.value.map(write).asJava)
                case o: JsObject => res.setM(o.value.mapValues(write).asJava)
                case JsNull => res.setNULL(true)
            }
            res
        }
    }