I see at least two options how to handle this:
- Use a List of Map
- Write a custom conversion function between (String, String) and JObject(JField(, JString())
Sometimes it is also useful working directly on the AST or extracting a plain Map[String, Any] via the values function. The Tuple2 conversion is valid as long as you are working with the JValue DSL, but not when doing extraction to/decomposition from Scala types.
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)))