JSON Operation by Scala

Recently, I’m doing a subscription system for my current company. The content of subscription is to crawl data from another system. The most important thing is that the data is async and from multiple channels. My solution is to use Akka scheduler to deal with async issue. For multiple channels, I use MySQL to store temp data together and finally fetch them again and email them.

So when I decide which data structure to use, I choose Map, but considering I need to use string/text to store data to DB. things became not good, because converting string to Map is not a good method. Now JSON helps me a lot.

1. import some libs

import play.api.libs.json._

2. build a JSON by Scala

var bufJson = new JsArray()
// here you need to return back, since append will not return back
bufJson = bufJson.append(Json.obj{"status" -> "add"})

3. transfer JSON to String

val dataString = bufJson.toString()

4. transfer string back to JSON

val dataJson = Json.parse(dataString)
dataJson match {
  case JsArray(dataJsArray) => {
    //do your own things
  }
  case _ => 
}

5. How to fetch data in JSON

// "time" is your key, dataJson is JsValue/JsObject which gets from Json.obj or Json.parse
val time = dataJson.\("time")
// you can convert the result to any type
val time = dataJson.\("time").as[String]
// if there is sub-JSON in result you can convert to JsObject to benefit next step
val time1 = dataJson.\("time").as[JsObject]

6. How to loop the JSON

dataJson.keys.foreach { 
  eachKey =>
    val eachValue = dataJson.\(eachKey)
    ..
}

7. How to update value in JSON

Here I list five cases:

(1) append new value to existing structure: see temp

(2) overwrite value directly to exact path: see temp1

(3) remove one path from json: see temp2

(4) read old value and overwrite this value, see temp3

(5) pick a branch and remove a sub-branch, see temp4

// figure out path and the field which you want to update
val temp = ( __ \ 'key1' \ 'key2').json.update(
  __.read[JsObject].map{ o => o ++ Json.obj("key3" -> "value3")})

// Or you want to overwrite its value, Note: JsString or JsNumber or others which is depended on your value. 
val temp1 = (__ \ 'key1' \ 'key2' \ 'key3' ).json.put(JsString(<your_value>))

// Or you want to remove one branch from your json
val temp2 = (__ \ 'key1' \ 'key2').json.prune

// or pick a value and then overwrite it
val temp3 = (__ \ 'key1' ).json.pickBranch(
  (__ \ 'key2').json.update(
    of[JsNumber].map{case JsNumber(nb) => JsNumber(nb + 10)
  ) and Then
  (__ \ 'key21').json.update(
    of[JsArray].map{case JsArray(arr) => JsArray(arr :+ JsString("abc"))}
  )
)

// or pick a branch and remove sub-branch
val temp4 = (__ \ 'key2').json.pickBranch(
  (__ \ 'key23').json.prune
)

// update to your json
val newJson = oldJson.transform(temp)
newJson match {
  case JsSuccess(value, path) =>
    // here value is your final json 
    ....
  case _ =>
}

Detailed API usage, you need to check its document.

Useful link:

https://www.playframework.com/documentation/2.2.x/ScalaJson

https://www.playframework.com/documentation/2.0/api/scala/play/api/libs/json/JsArray.html

https://www.playframework.com/documentation/2.3.x/ScalaJsonTransformers

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s