Сохранение JsObject в DynamoDB - PullRequest
       7

Сохранение JsObject в DynamoDB

0 голосов
/ 27 апреля 2018

Мы хотим сохранить наши модели данных в DynamoDB. Мы используем Scanamo с Alpakka для неблокирующего ввода / вывода. По многим причинам мы не хотим, чтобы ключи и данные автоматически генерировались в динамо-формате. У нас уже есть форматеры Play-Json для всех наших классов дел и мы хотим, чтобы данные сохранялись в Dynamo из JsObjects.

Для сохранения данных в виде JsObject каждый репозиторий имеет следующий

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

Всегда получаю эту ошибку:

не удалось найти неявное значение для параметра улик типа com.gu.scanamo.DynamoFormat [play.api.libs.json.JsObject]

Я не могу найти способ заставить его принять JsObject или создать подходящий форматировщик. Буду очень признателен за любую помощь.

Sidenote: Я смотрел на PlayDynamo-Repo , но они фактически создают весь запрос с нуля, и мы хотели бы использовать API Scanamo.

1 Ответ

0 голосов
/ 11 мая 2018

В итоге я использовал следующий код, который работает так, как ожидалось. Я не могу поделиться подфункциями, но это должно дать общее представление.

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
    }
}
...