1

Consider the following example JSON:

properties: {
    "key1": "a",
    "key2": 1,
    "key3": null,
    "key4": 0.56
    ....
    "key99": "zzzzz"
}

My code needs to be able to parse that into some sort of Scala structure (case class?) and back into JSON.

To me, since there are not a finite number of elements inside of properties, this looks like a Map[String, T]. And since the value of each inner property can be of multiple types, I'm not entirely sure how to represent that as a finite Scala structure. The documentation on implicit Reads, Writes, and Formats make sense to me, but they don't seem to handle more complicated examples, like the above.

It's also entirely possible I'm thinking about this completely wrong.

I'm new to the framework (as well as the language) and I'm having a hard time wrapping my head around how this should be represented -- any insight would be greatly appreciated.

3
  • 1
    What do you want to do with your data, considering that you don't know what keys or what type of values it can contain? As you need to serialize it to JSON later anyway, it seems Json transformer is your thing. playframework.com/documentation/2.4.x/ScalaJsonTransformers
    – Tyth
    Commented Sep 24, 2015 at 14:01
  • I'm building an app that currently takes an HTTP request similar to the above, translates it to a Scala object, augments it with more key/values, converts it back to JSON, and proxies the request to another system. Your response thought has me thinking about this another way -- it's possible I don't need this to be converted to a case class -- I could just use it as a JsValue. This feels like I'm side-stepping the actual issue though; I'm still interested in how you'd accomplish such a thing.
    – clocklear
    Commented Sep 24, 2015 at 14:30
  • @clocklear Do you need the values in the json to augment the new ones? Commented Sep 24, 2015 at 14:47

1 Answer 1

1

As @Tyth pointed out, we may want to reconsider the structure of your json. Maybe something like:

{ [ { "key" : "key1", "value" : "a" }, { "key" : "key2", "value" : "1" }, .....

will be better...

Nevertheless, to answer your question you may do:

import play.api.libs.json._
val a = """{
 |     "key1": "a",
 |     "key2": 1,
 |     "key3": null,
 |     "key4": 0.56 }
 | """
 val b = Json.parse(a)
 val keys = b.as[JsObject].keys

And you can print your keys

scala> keys.foreach { k => println( b \ k ) }
"a"
1
null
0.56

Or turn then into a map of JsValue

scala> keys.map { k => k -> (b \ k) }.toMap
res4: scala.collection.immutable.Map[String,play.api.libs.json.JsValue] = Map(key1 -> "a", key2 -> 1, key3 -> null, key4 -> 0.56)

Or Strings:

scala> keys.map { k => k -> (b \ k).toString }.toMap
res3: scala.collection.immutable.Map[String,String] = Map(key1 -> "a", key2 -> 1, key3 -> null, key4 -> 0.56)

EDIT (per augment comment):

    scala> JsObject(b.as[JsObject].fields :+  ("key99" -> JsString("zzzz")))
res7: play.api.libs.json.JsObject = {"key1":"a","key2":1,"key3":null,"key4":0.56,"key99":"zzzz"}
1
  • Thanks for the insight! I suspect this is enough information for me to proceed with my project.
    – clocklear
    Commented Sep 24, 2015 at 15:37

Not the answer you're looking for? Browse other questions tagged or ask your own question.