Argonaut.io:كيفية إعادة تسمية خاصية جسون لليمين / اليسار في فئة الحالة التي تحتوي على أي منهما
سؤال
في أرجونوت ، كيف يمكن للمرء بسهولة إعادة تسمية اسم الخاصية جسون المقابلة في الحالات التي تحتوي على فئة حالة إما.
على سبيل المثال ، بالنظر إلى هذا التعريف:
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")
تحويل أ FooBar
إلى جسون مثل FooBar(Right(Bar("hello"))).asJson.spaces4
النتائج في ما يلي:
{
"e" : {
"Right" : {
"b" : "hello"
}
}
}
ما هي أسهل طريقة لإعادة تسمية "الحق" إلى شيء أكثر وضوحا في الإخراج أعلاه?(يحتوي السيناريو الفعلي الخاص بي على العديد من فئات الحالات مع العديد من الحالات ، لذلك أبحث عن الطريقة الأكثر إيجازا الممكنة.)
المحلول
إليك نهج مباشر بشكل معقول:
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")))
)
ثم:
val fooOrBar = namedEitherCodec[Foo, Bar]("Foo", "Bar")
implicit def FooBarCodecJson: CodecJson[FooBar] = casecodec1(
FooBar.apply, FooBar.unapply
)("e")(fooOrBar, fooOrBar)
يمكنك أيضا جعل fooOrBar
تميل مثيلات فئة النوع الضمنية ولكن المهيمنة بهذه الطريقة إلى الاستياء.
لا تنتمي إلى StackOverflow