Search code examples
jsonscalaplay-json

How can I read Json as Map[String,String]?


I got the problem when parsing JSON to Map[String, String]. The idea is to parse the nested object to a key separate by "."

Can we format this input JSON:

{
   "key-1":{
       "sub-key-1-1":{
           "sub-key-1-1-1":"value111"
        },
        "sub-key-1-2":{
           "sub-key-1-2-1":"value121"
        }
    },
    "key-2":{
       "sub-key-2-1":{
           "sub-key-2-1-1":"value211"
       }
    }
}

to this result as Map[String,String]:

("key-1.sub-key-1-1.sub-key-1-1-1"->"value111", 
"key-1.sub-key-1-2.sub-key-1-2-1"->"value121",
"key-2.sub-key-2-1.sub-key-2-1-1"->"value211")

Solution

  • You can think about it this way, if the JsValue is a JsObject, you need to extract the key values and append them to the current state of your function, if it's anything else, you can just add them to the state of your function, and then return them. Thinking recursively:

    import play.api.libs.json._
    
    def iterateJson(js: JsValue, currentKey: Option[String] = None, acc: Map[String, String] = Map.empty): Map[String, String] = {
        js match {
          case obj: JsObject =>
            obj.keys.foldLeft(acc) {
              case (updatingMap, newKey) =>
                iterateJson(obj.value(newKey), currentKey.map(k => s"$k.$newKey") orElse Some(newKey), updatingMap)
            }
          case other =>
            (currentKey map (key => acc.updated(key, other.toString()))) getOrElse acc
        }
      }
    

    See the code running on scastie