0

In Scala, how can I de-serialize a JSON string, modify a value and serialize back to string?

There has to be a way to do this without using 3rd party libraries but I can't get it to work. Here is what I tried so far:

import scala.util.parsing.json

var lines = "{\"id\" : \"abc\", \"stuff\" : [1, 2, 3], \"more\" : {\"bro\" : \"science\"}}"

// Test 1
val myJSON = json.JSON.parseRaw(lines)
// myJSON: Option[scala.util.parsing.json.JSONType] = Some({"id" : "abc", "stuff" : [1.0, 2.0, 3.0], "more" : {"bro" : "science"}})
// I cannot modify fields on the JSONType instance but toString() works well.
// res1: String = Some({"id" : "abc", "stuff" : [1.0, 2.0, 3.0], "more" : {"bro" : "science"}})

// Test 2
// This way I can parse JSON into a map and manipulate its values.
// val myMap = json.JSON.parseFull(lines).get.asInstanceOf[Map[String, Any]] + ("id" -> "blah")
// myMap: scala.collection.immutable.Map[String,Any] = Map(id -> blah, stuff -> List(1.0, 2.0, 3.0), more -> Map(bro -> science))

// However, when converted to an instance of JSONObject and calling
// toString() only the top-level items are JSON-serialized
new json.JSONObject(myMap).toString()
// res2: String = {"id" : "blah", "stuff" : List(1.0, 2.0, 3.0), "more" : Map(bro -> science)}

If it's not possible with standard Scala, I'd appreciate and example of how to do this with a third party library.

Thanks,

/David

OG Dude
  • 936
  • 2
  • 12
  • 22
  • 1
    Possible duplicate of http://stackoverflow.com/questions/4170949/how-to-parse-json-in-scala-using-standard-scala-classes, though nowadays the JSON parser with parser combinators seems to be deprecated (too slow, unmaintained). Looking for alternatives: http://softwarerecs.stackexchange.com/. – Gábor Bakos Feb 09 '15 at 12:24
  • 5
    There are many JSON libs (e.g. Argonaut, Play-Json, Lift-Json, ...) – cchantep Feb 09 '15 at 12:41
  • Ive been using https://github.com/json4s/json4s with some success. It has a nice API. – Rich Henry Feb 09 '15 at 14:06
  • Play JSON has JSON transformers which will accomplish this. – Barry Feb 09 '15 at 14:22

1 Answers1

1

small silly/trivial example of what I mentioned. Could be written better too but wanted to break it into chunks. There is a lot you can do with them:

Here is old link in terms of play version but as far as I know up to date on features available in 2.3.x:

https://www.playframework.com/documentation/2.1.1/ScalaJsonTransformers

import play.api.libs.json._

var lines = "{\"id\" : \"abc\", \"stuff\" : [1, 2, 3], \"more\" : {\"bro\" :        \"science\"}}"

val jsonAsJsValue = Json.parse(lines)
//jsonAsJsValue: play.api.libs.json.JsValue = {"id":"abc","stuff":    [1,2,3],"more":{"bro":"science"}}
val updateIdTransformer =  (__ \"id").json.update(
 __.read[JsString].map{a => JsString("def")}
)

val updatedJson = jsonAsJsValue.transform(updateIdTransformer)

//updatedJson: play.api.libs.json.JsResult[play.api.libs.json.JsObject] =    JsSuccess({"id":"def","stuff":[1,2,3],"more":{"bro":"science"}},/id)
Barry
  • 1,800
  • 2
  • 25
  • 46