0
var json= {"a1":"b","c1":"d","e1":{"f1":"g","h1":"i","j1":"k"}}
implicit val formats = org.json4s.DefaultFormats
parse(json).extract[Map[String, String]]

I am getting NullPointerException when i execute the code. The NPE is because formats is null. Do I need to use some different format ?

sailor
  • 753
  • 1
  • 6
  • 17
  • Exception in thread "main" org.json4s.MappingException: unknown error Caused by: java.lang.NullPointerException at org.json4s.Extraction$.convert(Extraction.scala:424) at org.json4s.Extraction$.org$json4s$Extraction$$build$1(Extraction.scala:325) at org.json4s.Extraction$$anonfun$org$json4s$Extraction$$build$1$5.apply(Extraction.scala:339) at org.json4s.Extraction$$anonfun$org$json4s$Extraction$$build$1$5.apply(Extraction.scala:339) at scala.collection.immutable.List.map(List.scala:288) – sailor Nov 22 '17 at 12:30
  • BEWARE: [json4s is vulnerable under DoS/DoW attacks!](https://github.com/json4s/json4s/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+denial) – Andriy Plokhotnyuk Jul 04 '22 at 08:38

2 Answers2

0

You can not extract like this because you are returning Map[String, String] but your input e1 contains Array. So you can use case class for extracting the value:

case class Data(a1: String, c1: String, e1: ArrayData)

case class ArrayData(f1: String, h1: String, j1: String)

def checkData : Data = {
    val json = """{"a1":"b","c1":"d","e1":{"f1":"g","h1":"i","j1":"k"}}"""
    implicit val formats = org.json4s.DefaultFormats
    parse(json).extract[Data]
  }

// output : Data(b,d,ArrayData(g,i,k))

Thanks.

Learner
  • 1,170
  • 11
  • 21
  • e1 is another nested json, unfortunately its not the array, i wanted to make it another map. and i cant go with case class, because, the structure of input json is not fixed, but its the nested json at any level, such as {a1: { b1:"c", d1:"e"}, f1:"g"}. i changed my return type to Map[Any, Any] but no sucess – sailor Nov 22 '17 at 14:19
0

Though it is a 4-year-old question, I wanted to give another look at the problem because converting JSON document structure is universal.

Parsing a JSON document with all fields requires a substantial amount of work. but if you don't need all the fields and the part you need is not changing, then this would be the way to extract the data needed.

var json= """{"a1":"b","c1":"d","e1":{"f1":"g","h1":"i","j1":"k"}}"""
implicit val formats = org.json4s.DefaultFormats
data=parse(json)

val a1 = (data \ "a1").extract[String]
val c1 = (data \ "c1").extract[String]

val e1 = data \ "e1"
val f1 = (e1 \ "f1").extract[String]
val h1 = (e1 \ "h1").extract[String]
val j1 = (e1 \ "j1").extract[String]

val e1 = data \ "e1" gives clue on how to handle sub objects.

@Learner's answer has a few key points though. we need a stringified JSON data to start with and we can use predefined classes if the data structure is not changing.

Remembering JSON has limited number of data types, this can be an easy task for small structures but the flexibility of JSON will make it hard when the structure grows big. Then you will either need to give up the flexible data or work hard for writing extractor classes for deep/complex data.

Yılmaz Durmaz
  • 2,374
  • 12
  • 26