Argonauta.io:cómo cambiar el nombre de la propiedad json a Derecha/Izquierda en caso de que la clase contenga Cualquiera

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

  •  20-12-2019
  •  | 
  •  

Pregunta

En Argonaut, ¿cómo se puede cambiar fácilmente el nombre de la propiedad JSON correspondiente en los casos en que una clase de caso contiene cualquiera de los dos?

Por ejemplo, dada esta definición:

  case class Foo(f: String)
  case class Bar(b: String)
  case class FooBar(e: Either[Foo, Bar])

  implicit def FooCodecJson: CodecJson[Foo] = casecodec1(Foo.apply, Foo.unapply)("f")

  implicit def BarCodecJson: CodecJson[Bar] = casecodec1(Bar.apply, Bar.unapply)("b")

  implicit def FooBarCodecJson: CodecJson[FooBar] = casecodec1(FooBar.apply, FooBar.unapply)("e")

convirtiendo un FooBar a JSON como FooBar(Right(Bar("hello"))).asJson.spaces4 resulta en lo siguiente:

{
    "e" : {
        "Right" : {
            "b" : "hello"
        }
    }
}

¿Cuál es la forma más sencilla de cambiar el nombre de "Derecha" a algo más significativo en el resultado anterior?(Mi escenario real tiene muchas clases de casos con muchos Ambos, por lo que busco la forma más concisa posible).

¿Fue útil?

Solución

He aquí un enfoque razonablemente sencillo:

def renameFields(replacements: (JsonField, JsonField)*)(json: Json) =
  json.withObject(obj =>
    replacements.foldLeft(obj) {
      case (acc, (before, after)) => 
        acc(before).map(v => (acc - before) + (after, v)).getOrElse(acc)
    }
  )

def renamedEitherCodec[A, B](leftName: String, rightName: String)(implicit
  ee: EncodeJson[Either[A, B]],
  de: DecodeJson[Either[A, B]]
) = CodecJson[Either[A, B]](
  e => renameFields("Left" -> leftName, "Right" -> rightName)(ee(e)),
  c => de(c.withFocus(renameFields(leftName -> "Left", rightName -> "Right")))
)

Y luego:

val fooOrBar = namedEitherCodec[Foo, Bar]("Foo", "Bar")

implicit def FooBarCodecJson: CodecJson[FooBar] = casecodec1(
  FooBar.apply, FooBar.unapply
)("e")(fooOrBar, fooOrBar)

También podrías hacer el fooOrBar Las instancias de clase de tipo implícitas, pero anuladoras de esa manera, tienden a ser mal vistas.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top