Я написал Reads
конвертер в play-json для Option[Option[A]]
, который имел следующее поведение:
//given this case class
case class MyModel(field: Option[Option[String]])
//this JSON -- maps to --> this MyModel:
//"{ \"field\": \"value\" }" --> MyModel(field = Some(Some("value")))
//"{ \"field\": null, ... }" --> MyModel(field = Some(None))
//"{ }" --> MyModel(field = None)
Таким образом, предоставляя значение, сопоставленное с Some[Some[A]]
, предоставляя null
сопоставленное с Some[None]
(т.е. Some[Option.empty[A]]
), и не предоставляя значение, сопоставленное только с None
(то есть Option.empty[Option[A]]
). Вот конвертер play-json:
def readOptOpt[A](implicit r: Reads[A]): Reads[Option[Option[A]]] = {
Reads[Option[Option[A]]] { json =>
path.applyTillLast(json).fold(
identity,
_.fold(_ => JsSuccess(None), {
case JsNull => JsSuccess(Some(None))
case js => r.reads(js).repath(path).map(a => Some(Some(a)))
})
)
}
}
Сейчас я конвертирую свой код play-json в Circe, но не могу понять, как написать Decoder[Option[Option[A]]
с таким же поведением. То есть мне нужно
def optOptDecoder[A](implicit d: Decoder[A]): Decoder[Option[Option[A]] = ??? //help!
Любые идеи о том, как я могу заставить эту работу? Спасибо
Я разобрался в этом:
Было две проблемы:
1) Что делать в случае, когда поле полностью отсутствовало в JSON. Оказывается, вы должны использовать Decoder.reattempt
в своем собственном декодере, следуя коду Цирцеи decodeOption
, который работает.
2) Как заставить компилятор распознавать случаи Option[Option[A]]
, когда код вашего декодера находится во вспомогательном объекте (или где-то еще). Оказывается, если вы используете полуавтоматический вывод, вы можете создать неявный объект в сопутствующем объекте, который переопределит значения по умолчанию:
//companion object
object MyModel {
implicit def myModelOptOptDecoder[A](implicit d: Decoder[A]): Decoder[Option[Option[A]]] =
MyHelperObject.optOptDecoder
implicit val myModelDecoder: Decoder[MyModel] = deriveDecoder
}
В любом случае, я не думаю, что это сильно поможет кому-либо в будущем, поэтому, если я не получу никаких голосов в ближайшие несколько часов, я думаю, что просто удалю это.
Edit2: Хорошо, на него ответили, поэтому я не буду его удалять. Оставайся сильным, эзотерический вопрос о круге, оставайся сильным ...
Decoder[Option[Option[A]]
при столкновении с[Option[Option[A]]
, поскольку Circe, похоже, просто с радостью просто использует свой декодерOption
по умолчанию и в этом случае. Фу. - person Lasf   schedule 20.09.2018Option[Option[T]]
имеет смысл? - person cchantep   schedule 21.09.2018None
). Нулевые значения поля удаляются из модели (это обозначается _2 _..., т. Е. Предпринимает какое-то действие, и это действие перезаписывается наNone
). Остальные значения полей обновлены (Some[Some[A]]
). В любом случае, я близок к тому, чтобы понять это (я думаю), поэтому я либо удалю q, либо отвечу на него сам, чтобы он мог бесполезно отдыхать всю вечность. - person Lasf   schedule 21.09.2018Option[A]
декодер не работает сOption[Option[A]]
? - person sarveshseri   schedule 21.09.2018Option[Option[A]]
в вашем случае - person crak   schedule 23.01.2019