Écrivez une valeur arbitraire introuvable dans une classe de cas à l'aide des combinateurs Scala JSON de Play (2.2)

StackOverflow https://stackoverflow.com//questions/23019485

Question

J'aimerais mettre en œuvre un Writes qui émet un objet JSON introuvable dans la classe en cours de sérialisation.

Pour la classe de cas :

case class Foo(i:Int, s:String)

Je cherche à produire :

{
  "i": <int>,
  "s": "<string>",
  "other": "Some value."
}

La première tentative naïve était la suivante :

val writes: Writes[Foo] = ((
  (__ \ "i").write[Int] and
    (__ \ "s").write[String] and
    (__ \ "other").write("Some value.")
  )(unlift(Foo.unapply))

Naturellement, cela ne sera pas compilé comme suit and les appels produisent un CanBuild3 et Fooc'est unapply produit un Tuple2.J'avais envisagé d'ajouter une valeur au résultat, produisant ainsi un Tuple3, mais ce que j'ai trouvé ça a l'air plutôt mauvais et le les responsables du langage ne l'implémenteront pas.

Il existe des moyens de contourner ce problème, mais je préfère ne pas polluer mes classes de modèles avec ces valeurs de décorateur que j'aimerais ajouter au JSON résultant.

Aucune suggestion?

Ça vaut la peine de te noter peut aller dans l'autre sens, en fournissant des valeurs avec Reads.pure pour les cas où une valeur n'existe pas dans JSON mais est spécifiée par l'objet résultant.

Était-ce utile?

La solution

Vous pouvez le faire assez simplement en désucrant un peu :

val writes: Writes[Foo] = (
  (__ \ "i").write[Int] and
  (__ \ "s").write[String] and
  (__ \ "other").write[String]
)(foo => (foo.i, foo.s, "Some value."))

Le unlift(Foo.unapply) est juste une façon sophistiquée d'obtenir une fonction d'un Foo à un tuple du type requis par l'expression du générateur applicatif précédente, et vous pouvez le remplacer par votre propre fonction qui peut ajouter ce que vous voulez.

Si tu vraiment vous vouliez une syntaxe encore plus propre, vous pouvez utiliser Informe:

import shapeless.syntax.std.tuple._

val writes: Writes[Foo] = (
  (__ \ "i").write[Int] and
  (__ \ "s").write[String] and
  (__ \ "other").write[String]
)(_ :+ "Some value.")

C'est beau, mais c'est peut-être exagéré.

Autres conseils

Une autre option consiste à utiliser un générateur d'objets qui implémente un unapply qui renvoie les valeurs supplémentaires.Cela rend les écritures plus propres, mais ajoute un nouvel objet.J'ai trouvé cela utile, car les méthodes d'application et de désapplication peuvent être utilisées pour un massage supplémentaire des données dans l'objet final (par exemple : https://stackoverflow.com/a/22504468/1085606)

Exemple:

case class Foo(i: Int, s: String)

object FooBuilder {
  def unapply(foo: Foo): Option[(Int, String, String)] = {
    Some((foo.i, foo.s, "Some extra value"))
  }
}

val writes: Writes[Foo] = ((
  (__ \ "i").write[Int] and
    (__ \ "s").write[String] and
    (__ \ "other").write[String]
  )(unlift(FooBuilder.unapply))
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top