2

次の JSON が与えられます。

{
    "foo": "bar",
    "baz":[
        { "qux" : "quux" },
        { "quuux" : "quuuux" }
    ]
}

それを Scala ケース クラスとして表現する最良の方法は何ですか? 論理的には、次のようになるはずです。

case class Foo(
  foo: String,
  baz: List[(String, String)]
)

ただし、これを Json4s と Jackson で解析しようとすると、次のようになります。

No usable value for baz
No usable value for _1
Did not find value which can be converted into java.lang.String
org.json4s.package$MappingException: No usable value for baz
No usable value for _1
Did not find value which can be converted into java.lang.String

逆に、予想を構築するとFoo...

val foo = Foo(foo = "bar", baz = List(("qux" -> "qux1"), ("qux" -> "qux2")))

...そしてそれをJSONとして書くと、タプルのリストを取得できません。次のようになります:

{
  "foo" : "bar",
  "baz" : [ {
    "_1" : "qux",
    "_2" : "qux1"
  }, {
    "_1" : "qux",
    "_2" : "qux2"
  } ]
}

この回答では、Json4sが DSLからオブジェクトを生成すると主張Tuple2sしているにもかかわらず、オブジェクト フィールドがJValue. Fooモデルオブジェクトをシリアライズおよびデシリアライズする以外に他のことをしたいので、 JValues.

それを考えると、私はここで何をすべきですか?

4

1 に答える 1

1

これを処理する方法として、少なくとも 2 つのオプションがあります。

  1. マップのリストを使用する
  2. (String, String) と JObject(JField( , JString( ))の間のカスタム変換関数を記述します。

AST で直接作業したり、 values関数を介してプレーンな Map[String, Any] を抽出したりすることも役立つ場合があります。Tuple2 変換は、JValue DSL を使用している限り有効ですが、Scala 型への抽出/分解を行う場合は有効ではありません。

import org.json4s._
import org.json4s.jackson.JsonMethods._
import org.json4s.JsonDSL._

val json = """{
             |    "foo": "bar",
             |    "baz":[
             |        { "qux" : "quux" },
             |        { "quuux" : "quuuux" }
             |    ]
             |}""".stripMargin

class StringTupleSerializer extends CustomSerializer[(String, String)](format => ( {
  case JObject(List(JField(k, JString(v)))) => (k, v)
}, {
  case (s: String, t: String) => (s -> t)
}))

implicit val formats = DefaultFormats + new StringTupleSerializer

case class FooMap(foo: String, baz: List[Map[String, String]])

case class FooTuple(foo: String, baz: List[(String, String)])

val ast = parse(json)

println(ast.extractOpt[FooMap])
//  Some(FooWithMap(bar,List(Map(qux -> quux), Map(quuux -> quuuux))))

println(ast.extractOpt[FooTuple])
//  Some(FooWithTuple(bar,List((qux,quux), (quuux,quuuux))))

val foo1 = FooMap(foo = "bar", baz = List(Map("qux" -> "qux1"), Map("qux" -> "qux2")))
val foo2 = FooTuple(foo = "bar", baz = List(("qux" -> "qux1"), ("qux" -> "qux2")))

println(pretty(Extraction.decompose(foo1)))
println(pretty(Extraction.decompose(foo2)))
于 2014-02-05T01:04:16.860 に答える