Запись пользовательского объекта JSON в виде простого значения в Scala (чтение/запись JSON)

У меня есть пользовательский тип данных в Scala:

case class GPID(value: Int) {
    // ... other stuff ...

    implicit val writesGPID = new Writes[GPID] {
        def writes(g: GPID): JsValue = {
            Json.obj(
                "GPID" -> g.value
            )
        }
    }

    implicit val reads: Reads[GPID] = (
        (__ \ "GPID").read[Int]
        ).map(GPID(_))
}

Как видите, у него есть метод чтения/записи, но это приводит к следующему результату:

"идентификатор":{"GPID":1000}

Но мы просто хотим, чтобы он сериализовался/десериализовался как обычный Int:

"id":1000

Я пытался выяснить, как переписать операции чтения/записи, но мне не очень повезло... Буду признателен за любые советы!

Спасибо.


person Zac    schedule 20.05.2015    source источник


Ответы (1)


Я добавил некоторую проверку, исправьте ваши потребности.

object GPID {
  def unapply(in: Int): Option[GPID] = Option(in).filter(_ > 0).map(apply)

  implicit val reads = new Reads[GPID] {
    def reads(in: JsValue) =
      Option(in)
        .flatMap {
          case JsNumber(value) => Some(value)
          case _ => None
        }
        .flatMap(num => unapply(num.toInt))
        .map(JsSuccess(_, __))
        .getOrElse(JsError(__, "validate.error.expected.GPID"))
  }

  implicit val writes = new Writes[GPID] {
    def writes(g: GPID) = JsNumber(g.value)
  }

}
person goralph    schedule 20.05.2015
comment
Хм. Ближе, но не совсем. Он сериализуется как "id":{"id":1000}, поэтому он по-прежнему обрабатывает его как объект, а не как простое значение... Также я не могу использовать неявное чтение из-за: ScalaReflectionException: value apply encapsulates multiple overloaded alternatives and cannot be treated as a method. Consider invoking <offending symbol>.asTerm.alternatives and manually picking the required method - person Zac; 20.05.2015
comment
Так что вам нужно предоставить один! Еще раз отредактировал. - person goralph; 20.05.2015
comment
Ах... Ваше неприменение сильно отличается от того, что я пробовал! Спасибо, теперь это работает отлично. Я немного смущен тем, почему мы должны добавить unapply сейчас, когда в нем нет необходимости, если мы определяем исходные операции чтения/записи (из моего первого поста). Надо будет повнимательнее посмотреть и разобраться. Json Reads/Writes/apply/unapply для меня все еще немного черной магии... - person Zac; 20.05.2015
comment
Они волшебны в том, что дают множество способов добиться одного и того же эффекта. Поначалу это пугает и разочаровывает, однако, как только вы к этому привыкнете, они станут довольно мощными. Удачи. - person goralph; 20.05.2015
comment
Когда дело доходит до unapply, я написал им, что они ожидают деконструкции класса. Я попробовал unapply(g: GPID), но вы написали unapply(in: Int), который вы вызываете непосредственно из операций чтения... и я все еще в замешательстве. Я не понимаю, почему и как это могло бы работать... Я думал, что unapply используется для существенной деконструкции экземпляра вещи. В данном случае речь идет о GPID, так что... как unapply может принимать Int и работать? На самом деле то, что вы написали как unapply, мне кажется методом apply! - person Zac; 20.05.2015