Search code examples
jsonscalaredisjson4s

Ways for converting key value string to Scala Map


I'm reading data from a KV store (Redis) in this case. The data returned is in the following format.

 { "key1":"value1", "key2":"value2", "key3":"value3" ...} 

Key is String and value is Int. I want to convert it into a Map[String,Int]

I looked at the json4s JSON API and my current code looks like the following. Is there a better/easier/cleaner way of doing this?

  //send a async query to Redis to
  val queryFuture  = redis.zrangebyscore[String](tablename, keymin, keymax )


  queryFuture.onComplete {
    case Success(datarows) =>
      println(s"Got %d rows of type %s for the query successfully".format(datarows.length))
      val jsonrows = for { x <- datarows.toList }
        yield parse(x)
      println("Got json rows %d".format(jsonrows.size))
      val mapdata = jsonrows.map(x => x.extract[Map[String,String]]).map( x => x.mapValues(_.toInt))

      //need to do something with this data now
    case Failure(y) =>
      println(s" there was some failure in getting the data from Redis")
  }

Solution

  • Your Json4s solution looks fine. Alternatively you can use mapField to transform the fields of a JObject and after that extract value of type Map[String, Int].

    val json1 = parse(
      """
        |{
        |  "key1": "1024",
        |  "key2": "2048",
        |  "key3": "4096"
        |}
      """.stripMargin)
    
    val json2 = json1.mapField {
      case (key, JString(value)) => (key, JInt(value.toInt))
      case x => x
    }
    
    val res = json2.extract[Map[String, Int]]
    
    println(res)
    // Map(key1 -> 1024, key2 -> 2048, key3 -> 4096)