У меня есть требование проанализировать объект JSON, используя play-json, и различать отсутствующее значение, строковое значение и нулевое значение.
Так, например, я мог бы захотеть десериализоваться в следующий класс case:
case class MyCaseClass(
a: Option[Option[String]]
)
Где значения «а» означают:
- Нет - отсутствовала буква "a" - нормальное поведение play-json
- Some(Some(String)) - "a" имело строковое значение
- Some(None) - "a" имело нулевое значение
Итак, примеры ожидаемого поведения:
{}
should deserialize to myCaseClass(None)
{
"a": null
}
should deserialize as myCaseClass(Some(None))
{
"a": "a"
}
should deserialize as myCaseClass(Some(Some("a"))
Я пробовал писать собственные средства форматирования, но методы formatNullable и formatNullableWithDefault не различают отсутствующее и нулевое значение, поэтому код, который я написал ниже, не может генерировать результат Some(None)
object myCaseClass {
implicit val aFormat: Format[Option[String]] = new Format[Option[String]] {
override def reads(json: JsValue): JsResult[Option[String]] = {
json match {
case JsNull => JsSuccess(None) // this is never reached
case JsString(value) => JsSuccess(Some(value))
case _ => throw new RuntimeException("unexpected type")
}
}
override def writes(codename: Option[String]): JsValue = {
codename match {
case None => JsNull
case Some(value) => JsString(value)
}
}
}
implicit val format = (
(__ \ "a").formatNullableWithDefault[Option[String]](None)
)(MyCaseClass.apply, unlift(MyCaseClass.unapply))
}
Я пропустил трюк здесь? Как мне это сделать? Я очень хочу закодировать конечное значение каким-либо другим способом, кроме Option[Option[Sting]], например, каким-то классом case, который инкапсулирует это:
case class MyContainer(newValue: Option[String], wasProvided: Boolean)
Option[Option[_]]
вряд ли может иметь какой-либо смысл в любом случае. Кстати, я не вижу пользы от такогоnull
/отсутствующего различия. - person cchantep   schedule 30.01.2018undefined
- person Aluan Haddad   schedule 13.05.2019null
vs опущено как два совершенно разных намерения. К сожалению, в спецификации JSON по этому поводу не меньше двусмысленности, но интуитивно мне имеет смысл делать то, что предлагает здесь @iandotkelly (особенно при рассмотрении PATCH). Я начал обсуждение этого вопроса с основной командой play-json здесь: discuss.lightbend.com/t/ - person kflorence   schedule 03.09.2020