Given, for example, the following JSON string:
[{"id": "user1", "password": "ps1"},{"id": "user2", "password": "ps2"},{"id": "user3", "password": "ps3"}]
What's the best and most optimized way to parse it in Scala and iterate through every result and analise it properly?
Thank you.
with Lift-JSON:
import net.liftweb.json.JsonParser._
import net.liftweb.json.DefaultFormats
val jsonString = //your jsonString....
case class Credential (id:String, password:String)
implicit val formats = DefaultFormats
val credentials = parse(jsonString).extract[List[Credential]]
credentials foreach { cred => println(cred.id + " " + cred.password) }
everything is explain here : http://www.assembla.com/spaces/liftweb/wiki/JSON_Support
I think this blogpost gives an comprehensive answer to your question: http://debasishg.blogspot.com/2011/02/applicatives-for-composable-json.html at the end there is also a link to a full source repository.
You could use lift-json library : http://www.assembla.com/spaces/liftweb/wiki/JSON_Support
Aside from lift-json, and the type class approach mentioned above, I know of spray-json (PEG parser), and twitter's json lib (based on the code in the Programming in Scala book) and the json lib in blueeyes. There are others!
I suggest taking a look at Jackson which is a mature and feature-rich library for JSON-parsing from Java.
Jackson has an "official" extension for scala: jackson-module-scala and another one Jerkson.
There's a JSON parsing library in the framework, built using the parser combinators: http://www.scala-lang.org/api/current/scala/util/parsing/json/package.html
Odersky and Venners walk you through it in their book, one of the last chapters.
Related
How to implementation in Kotlin(1.3 X) JVM String templating using Json content ?. I see lot of implementation in Java using Jackson and Velocity, Here I am looking for Kotlin based solution.
If I understood you correctly, you might use just raw string like this:
val greeting = "Hello"
val name = "World"
val json =
"""
{
"greeting": $greeting,
"name": $name
}
""".trimIndent()
Search for raw string in official documentation
A JSON string:
{
"name": "Mike",
"age": 111
}
A case class:
case class User(name:String, age:Int)
If I use scala, there are many libraries can let me convert the JSON to the case class and vice versa, but they can't be used in scala.js.
How to do this work in scala.js?
Use one of the pickling libraries that work with Scala.js. The following two produce well-behaved and predictable JSON:
uPickle
Prickle
Circe has more than 1000 stars:
https://github.com/circe/circe
More safe and efficient options are:
AVSystems GenCodec
Borer
jsoniter-scala
Bellow are results of benchmarks for parsing and serialization of a message sample from the Twitter API:
What is the fastest way to convert this
{"a":"ab","b":"cd","c":"cd","d":"de","e":"ef","f":"fg"}
into mutable map in scala ? I read this input string from ~500MB file. That is the reason I'm concerned about speed.
If your JSON is as simple as in your example, i.e. a sequence of key/value pairs, where each value is a string. You can do in plain Scala :
myString.substring(1, myString.length - 1)
.split(",")
.map(_.split(":"))
.map { case Array(k, v) => (k.substring(1, k.length-1), v.substring(1, v.length-1))}
.toMap
That looks like a JSON file, as Andrey says. You should consider this answer. It gives some example Scala code. Also, this answer gives some different JSON libraries and their relative merits.
The fastest way to read tree data structures in XML or JSON is by applying streaming API: Jackson Streaming API To Read And Write JSON.
Streaming would split your input into tokens like 'beginning of an object' or 'beginning of an array' and you would need to build a parser for these token, which in some cases is not a trivial task.
Keeping it simple. If reading a json string from file and converting to scala map
import spray.json._
import DefaultJsonProtocol._
val jsonStr = Source.fromFile(jsonFilePath).mkString
val jsonDoc=jsonStr.parseJson
val map_doc=jsonDoc.convertTo[Map[String, JsValue]]
// Get a Map key value
val key_value=map_doc.get("key").get.convertTo[String]
// If nested json, re-map it.
val key_map=map_doc.get("nested_key").get.convertTo[Map[String, JsValue]]
println("Nested Value " + key_map.get("key").get)
I want to convert a scala list of strings, List[String], to an Json object.
For each string in my list I want to add it to my Json object.
So that it would look like something like this:
{
"names":[
{
"Bob",
"Andrea",
"Mike",
"Lisa"
}
]
}
How do I create an json object looking like this, from my list of strings?
To directly answer your question, a very simplistic and hacky way to do it:
val start = """"{"names":[{"""
val end = """}]}"""
val json = mylist.mkString(start, ",", end)
However, what you almost certainly want to do is pick one of the many JSON libraries out there: play-json gets some good comments, as does lift-json. At the worst, you could just grab a simple JSON library for Java and use that.
Since I'm familiar with lift-json, I'll show you how to do it with that library.
import net.liftweb.json.JsonDSL._
import net.liftweb.json.JsonAST._
import net.liftweb.json.Printer._
import net.liftweb.json.JObject
val json: JObject = "names" -> List("Bob", "Andrea", "Mike", "Lisa")
println(json)
println(pretty(render(json)))
The names -> List(...) expression is implicitly converted by the JsonDSL, since I specified that I wanted it to result in a JObject, so now json is the in-memory model of the json data you wanted.
pretty comes from the Printer object, and render comes from the JsonAST object. Combined, they create a String representation of your data, which looks like
{
"names":["Bob","Andrea","Mike","Lisa"]
}
Be sure to check out the lift documentation, where you'll likely find answers to any further questions about lift's json support.
How could I extract values from the following response:
{"photosets":{"cancreate":1, "page":1, "pages":1, "perpage":1, "total":1, "photoset":
[{"id":"72157629171255321", "primary":"6817523143", "secret":"250f42ed7c", "server":"7166",
"farm":8, "photos":"1", "videos":0, "title":{"_content":"Set1"}, "description":{"_content":""},
"needs_interstitial":0, "visibility_can_see_set":1, "count_views":"0", "count_comments":"0",
"can_comment":1, "date_create":"1328373127", "date_update":"1328373159"}]}, "stat":"ok"}
I need some values not All of them for example I need "id" field How can I get it?
Thanks,
There is a very performant wrapper (because Jackson is...) for scala.
Jerkson will help you in doing this check this out.
val ids: Seq[JString] = parse[JValue]("""
{"photosets":{"cancreate":1, "page":1, "pages":1, "perpage":1, "total":1, "photoset":
[{"id":"72157629171255321", "primary":"6817523143", "secret":"250f42ed7c", "server":"7166", "farm":8, "photos":"1", "videos":0, "title":{"_content":"Set1"}, "description": {"_content":""}, "needs_interstitial":0, "visibility_can_see_set":1, "count_views":"0", "count_comments":"0", "can_comment":1, "date_create":"1328373127", "date_update":"1328373159"}]}, "stat":"ok"}
""") \\ "id"
Here is a HowTo, note the use of parse that will return a JValue, on which you can call \ or \\ that find on the first level or any the property given rigth after.
Using reflection, Jerkson is also available to parse directly in case class, check the documentation... it's very powerful
There isn't anything inherently Scala about this, just use a JSON parser like Jackson and extract the information that you need.