1

I have a a generic JSON where all keys and values are string.

Example1:

[
  {
    "key1": "value1"
  },
  {
    "key1": "value2"
  }
]

but the JSON can also be: Example2:

[
  {
    "key1": "value1",
    "key2": "value2"
  },
  {
    "key1": "value3",
    "key2": "value4"
  }
]

I want to convert the JSON to a Map. Example 1 will convert to Map[String, String]

Example 2 will convert to List[Map[String, String]]

So basically I want to convert the JSON to Map and use it as following:

map("key1")("key2")("key3")

to get the final result value3.

Please help!!

3
  • none of these examples are valid JSONs (you can see for yourself here: jsonformatter.curiousconcept.com) Commented Sep 16, 2016 at 9:27
  • map("key1")("key2")("key3") returns value3??? how is that? where did key3 came from?? Commented Sep 16, 2016 at 10:52
  • its a generic 'json'. you can have only one key in it or n keys also. I want to convert 'json' to nested map and would like to get map(k1)(k2)..(kn) Commented Sep 16, 2016 at 10:56

1 Answer 1

2

Using play-json you can convert Json to Map using validate. Validate returns JsResult which can be JsSuccess(data,path) or JsError(errors). Pattern match to get the map out of it.

Check if str is of case 1 if not fallback to case 2

Json.parse(jsonString).validate[Map[String, String]].getOrElse(json.validate[List[Map[String,String]]])

Case 1: For Map[String, String]

import play.api.libs.json._
val result = Json.parse(someValidJsonString).validate[Map[String, String]]
result match {
  case JsSuccess(map, _) => map
  case JsError(errors) => Logger.error("json parsing failed")
}

Case 2: For List[Map[String, String]]

import play.api.libs.json._
    val result = Json.parse(someValidJsonString).validate[List[Map[String, String]]]
    result match {
      case JsSuccess(list, _) => list
      case JsError(errors) => Logger.error("json parsing failed")
    }

Here someValidJsonString is the json string you want to convert to Map

If you are using sbt project then add play-json dependency to your project.

build.sbt

libraryDependencies ++= Seq("com.typesafe.play" %% "play-json" % "2.5.4")

Scala REPL

scala> import play.api.libs.json._
import play.api.libs.json._

scala> val map = Map("java" -> 1, "scala" -> 2)
map: scala.collection.immutable.Map[String,Int] = Map(java -> 1, scala -> 2)

scala> Json.toJson(map).validate[Map[String, Int]]
res3: play.api.libs.json.JsResult[Map[String,Int]] = JsSuccess(Map(java -> 1, scala -> 2),)

scala> val result = Json.toJson(map).validate[Map[String, Int]]
result: play.api.libs.json.JsResult[Map[String,Int]] = JsSuccess(Map(java -> 1, scala -> 2),)

scala> result match { case JsSuccess(data, _) => data case JsError(errors) => Unit}
res4: Object = Map(java -> 1, scala -> 2)
Sign up to request clarification or add additional context in comments.

3 Comments

The challenge is not just converting JSON to map, its nesting part so 1 'json' can be {{'k1': 'v1'}, {'k1':'v2'}} i.e. all entries have 1 element but other can be {{k1:v1, k2:v2}, {k1:v3, k2:v4} } so for case 1 i need Map[String, String] but for case 2 i need Map[String, Map[String, string]]
@satendra do you know when case 2 appears
I am trying to write code for a scenario where user puts files on platform and the system stores its entry to db which is in 'json', depending on number of columns there will be number of entries in each single 'json' but they will always be string so example1 corresponds to 1 column file and example2 for a file which has 2 columns.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.