簡體   English   中英

使用Json4s將JSON元組的列表表示為case類字段

[英]Representing a list of JSON tuples as a case class field, with Json4s

給定以下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否則它實際上不能對一個對象字段進行JValue 由於除了序列化和反序列化之外,我還想對Foo模型對象執行其他操作,因此我特別不想根據JValues定義它。

鑒於此,我應該在這里做什么?

我看到至少兩個選擇如何處理此問題:

  1. 使用地圖清單
  2. 在(String,String)和JObject(JField( ,JString( ))之間編寫自定義轉換函數

有時,直接在AST上運行或通過values函數提取純Map [String,Any]也很有用。 只要您正在使用JValue DSL,Tuple2轉換就有效,但是從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)))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM