Escrever um Valor Arbitrário Não foi Encontrado em um Caso de Classe Usando o Play (2.2) Scala JSON Ferramenta

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

Pergunta

Gostaria de implementar um Writes que emite um objeto JSON que não se encontra na classe que está sendo serializado.

Para o caso da classe:

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

Eu estou olhando para produzir:

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

A ingênua primeira tentativa foi:

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

Naturalmente, que não vai compilar como o subsequente and chamadas de produzir um CanBuild3 e Foo's unapply produz um Tuple2.Eu olhei para anexar um valor para o resultado, a produção de um Tuple3, mas o que eu encontrei parece muito ruim e o idioma mantenedores não implementá-lo.

Existem maneiras de contornar isso, mas eu prefiro não profanar o meu modelo de classes com estes decorador de valores que eu gostaria de incluir o resultante JSON.

Alguma sugestão?

É digno de nota que você pode vá para a outra direção, fornecendo valores com Reads.pure para os casos onde não existir um valor em JSON, mas é especificado pelo objeto resultante.

Foi útil?

Solução

Você pode fazer isso muito claramente por desugaring um pouco:

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

O unlift(Foo.unapply) é apenas uma maneira elegante para obter uma função a partir de uma Foo para que uma tupla do tipo exigido pelo anterior aplicativo construtor de expressão, e você pode substituí-lo com a sua própria função que pode adicionar o que você quiser.

Se você realmente queria mesmo aspirador de sintaxe, você pode usar Disforme:

import shapeless.syntax.std.tuple._

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

É bonita, mas pode ser um exagero.

Outras dicas

Outra opção é usar um construtor objeto que implementa um unapply que retorna a valores extra.Isto torna as Gravações de limpeza, mas adiciona um novo objeto.Eu encontrei este úteis, apesar de como aplicar e unapply método pode ser usado para extra massageando de dados para o objeto final (ex.: https://stackoverflow.com/a/22504468/1085606)

Exemplo:

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))
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top