131

I need to build a JSON string, something like this:

[
 { 'id': 1, 'name': 'John'},
 { 'id': 2, 'name': 'Dani'}
]
val jArray = JsArray();
jArray += (("id", "1"), ("name", "John"))
jArray += (("id", "2"), ("name", "Dani"))
println(jArray.dump)

I need to be able to add rows to the jArray, something like jArray += ...

What is the closest library/solution to this?

Jacek Laskowski
75k28 gold badges253 silver badges440 bronze badges
asked Nov 8, 2011 at 16:47
2

15 Answers 15

244

Unfortunately writing a JSON library is the Scala community's version of coding a todo list app.

There are quite a variety of alternatives. I list them in no particular order, with notes:

  1. parsing.json.JSON - Warning this library is available only up to Scala version 2.9.x (removed in newer versions)
  2. spray-json - Extracted from the Spray project
  3. Jerkson ± - Warning a nice library (built on top of Java Jackson) but now abandonware. If you are going to use this, probably follow the Scalding project's example and use the backchat.io fork
  4. sjson - By Debasish Ghosh
  5. lift-json - Can be used separately from the Lift project
  6. json4s 💣 § ± - An extraction from lift-json, which is attempting to create a standard JSON AST which other JSON libraries can use. Includes a Jackson-backed implementation
  7. Argonaut 💣 § - A FP-oriented JSON library for Scala, from the people behind Scalaz
  8. play-json ± - Now available standalone, see this answer for details
  9. dijon - A handy, safe and efficient JSON library, uses jsoniter-scala under hood.
  10. sonofjson - JSON library aiming for a super-simple API
  11. Jawn - JSON library by Erik Osheim aiming for Jackson-or-faster speed
  12. Rapture JSON ± - a JSON front-end which can use 2, 4, 5, 6, 7, 11 or Jackson as back-ends
  13. circe 💣 - fork of Argonaut built on top of cats instead of scalaz
  14. jsoniter-scala - Scala macros for compile-time generation of ultra-fast JSON codecs
  15. jackson-module-scala - Add-on module for Jackson to support Scala-specific datatypes
  16. borer - Efficient CBOR and JSON (de)serialization in Scala

💣 = has not fixed security vulnerabilities, § = has Scalaz integration, ± = supports interop with Jackson JsonNode

In Snowplow we use json4s with the Jackson back-end; we've had good experiences with Argonaut too.

Andriy Plokhotnyuk
8,0332 gold badges46 silver badges69 bronze badges
answered Jan 21, 2013 at 16:09

12 Comments

It's not true that lift-json is bundled within the larger LIft project, you can simply depend on lift-json and nothing else from the Lift project will come to your project.
@AlexDean: What's so bad about parsing.json.JSON?
Looks like the play-json will be released with Play 2.2 and you can already use it now: mandubian.com/2013/02/21/play-json-stand-alone
@BjornTipling - good point, can't find any mention now of it being deprecated in 2.11. Removed that comment
The list should put jackson-module-scala on the top, which has by far the best for the performance, simplicity, maintenance, and support.
|
17

Lift-json is at version 2.6 and it works really well (and is also very well supported, the maintainer is always ready to fix any bugs users may find. You can find examples using it on the github repository

The maintainer (Joni Freeman) is always reachable on the Lift mailing list. There are also other users on the mailing list who are very helpful as well.

As @Alexey points out, if you want to use the library with other Scala version, say 2.11.x, change scalaVersion and use %% as follows:

scalaVersion := "2.11.5" 
"net.liftweb" %% "lift-json" % "2.6"

You can check the liftweb.net site to find out the latest version as time goes by.

Prasad Khode
6,77912 gold badges47 silver badges62 bronze badges
answered Nov 8, 2011 at 17:06

4 Comments

I use lift-json as well and can vouch that it's a great library. It makes both parsing and generating/serializing JSON very easy.
+1 for "net.liftweb" % "lift-json_2.10" % "2.5.1"
and for Scala 2.11: "net.liftweb" % "lift-json_2.11" % "2.6-M4"
The lift-json object was archived. The best modern solution is upickle / ujson.
16

I suggest using jerkson, it supports most basic type conversions:

scala> import com.codahale.jerkson.Json._
scala> val l = List( 
 Map( "id" -> 1, "name" -> "John" ),
 Map( "id" -> 2, "name" -> "Dani")
 )
scala> generate( l )
res1: String = [{"id":1,"name":"John"},{"id":2,"name":"Dani"}]
answered Nov 8, 2011 at 16:52

3 Comments

It also has some really awesome support for case classes that can make for some very elegant and type-safe JSON handling.
This library has been abandoned by author, is there any alternative ?
Let's not forget about rapture.io, which "is a family of Scala libraries providing beautiful idiomatic Scala APIs for common programming tasks, like working with I/O, cryptography and JSON & XML processing."
12

Number 7 on the list is Jackson, not using Jerkson. It has support for Scala objects, (case classes etc).

Below is an example of how I use it.

object MyJacksonMapper extends JacksonMapper
val jsonString = MyJacksonMapper.serializeJson(myObject)
val myNewObject = MyJacksonMapper.deserializeJson[MyCaseClass](jsonString)

This makes it very simple. In addition is the XmlSerializer and support for JAXB Annotations is very handy.

This blog post describes it's use with JAXB Annotations and the Play Framework.

http://krasserm.blogspot.co.uk/2012/02/using-jaxb-for-xml-and-json-apis-in.html

Here is my current JacksonMapper.

trait JacksonMapper {
 def jsonSerializer = {
 val m = new ObjectMapper()
 m.registerModule(DefaultScalaModule)
 m
 }
 def xmlSerializer = {
 val m = new XmlMapper()
 m.registerModule(DefaultScalaModule)
 m
 }
 def deserializeJson[T: Manifest](value: String): T = jsonSerializer.readValue(value, typeReference[T])
 def serializeJson(value: Any) = jsonSerializer.writerWithDefaultPrettyPrinter().writeValueAsString(value)
 def deserializeXml[T: Manifest](value: String): T = xmlSerializer.readValue(value, typeReference[T])
 def serializeXml(value: Any) = xmlSerializer.writeValueAsString(value)
 private[this] def typeReference[T: Manifest] = new TypeReference[T] {
 override def getType = typeFromManifest(manifest[T])
 }
 private[this] def typeFromManifest(m: Manifest[_]): Type = {
 if (m.typeArguments.isEmpty) { m.erasure }
 else new ParameterizedType {
 def getRawType = m.erasure
 def getActualTypeArguments = m.typeArguments.map(typeFromManifest).toArray
 def getOwnerType = null
 }
 }
} 
answered Apr 2, 2013 at 6:47

Comments

8

Maybe I've late a bit, but you really should try to use json library from play framework. You could look at documentation. In current 2.1.1 release you could not separately use it without whole play 2, so dependency will looks like this:

val typesaferepo = "TypeSafe Repo" at "http://repo.typesafe.com/typesafe/releases"
val play2 = "play" %% "play" % "2.1.1"

It will bring you whole play framework with all stuff on board.

But as I know guys from Typesafe have a plan to separate it in 2.2 release. So, there is standalone play-json from 2.2-snapshot.

answered Jun 21, 2013 at 5:05

3 Comments

FYI: Play's JSON library is already available in Typesafe snapshots repo: repo.typesafe.com/typesafe/snapshots/com/typesafe/play/…
... which you can add like so.
It is officially used in the sbt tutorial
6

Here is a basic implementation of writing and then reading json file using json4s.

import org.json4s._
import org.json4s.jackson.JsonMethods._
import org.json4s.JsonDSL._
import java.io._
import scala.io.Source
object MyObject { def main(args: Array[String]) {
 val myMap = Map("a" -> List(3,4), "b" -> List(7,8))
 // writing a file 
 val jsonString = pretty(render(myMap))
 val pw = new PrintWriter(new File("my_json.json"))
 pw.write(jsonString)
 pw.close()
 // reading a file 
 val myString = Source.fromFile("my_json.json").mkString
 println(myString)
 val myJSON = parse(myString)
 println(myJSON)
 // Converting from JOjbect to plain object
 implicit val formats = DefaultFormats
 val myOldMap = myJSON.extract[Map[String, List[Int]]]
 println(myOldMap)
 }
}
answered May 14, 2015 at 22:02

Comments

5

You should check Genson. It just works and is much easier to use than most of the existing alternatives in Scala. It is fast, has many features and integrations with some other libs (jodatime, json4s DOM api...).

All that without any fancy unecessary code like implicits, custom readers/writers for basic cases, ilisible API due to operator overload...

Using it is as easy as:

import com.owlike.genson.defaultGenson_
val json = toJson(Person(Some("foo"), 99))
val person = fromJson[Person]("""{"name": "foo", "age": 99}""")
case class Person(name: Option[String], age: Int)

Disclaimer: I am Gensons author, but that doesn't meen I am not objective :)

answered Apr 13, 2015 at 11:55

1 Comment

Pretty dam cool, shame it has one issue github.com/owlike/genson/issues/82
4

Jawn is a very flexible JSON parser library in Scala. It also allows generation of custom ASTs; you just need to supply it with a small trait to map to the AST.

Worked great for a recent project that needed a little bit of JSON parsing.

answered Sep 2, 2014 at 10:35

Comments

4

Rapture seems to be missing in the list of the answers. It can be obtained from http://rapture.io/ and allows you (among other thing) to:

  • select JSON back-end, which is very useful if you already use one (in import)
  • decide if you work with Try, Future, Option, Either, etc. (also in import)
  • do a lot of work in a single line of code.

I don't want to copy/paste Rapture examples from it's page. A nice presentation about Rapture's features was given by Jon Pretty at SBTB 2014: https://www.youtube.com/watch?v=ka5-OLJgybI

answered Oct 9, 2014 at 7:05

Comments

3

@AlaxDean's #7 answer, Argonaut is the only one that I was able to get working quickly with sbt and intellij. Actually json4s also took little time but dealing with a raw AST is not what I wanted. I got argonaut to work by putting in a single line into my build.st:

libraryDependencies += "io.argonaut" %% "argonaut" % "6.0.1"

And then a simple test to see if it I could get JSON:

package mytest
import scalaz._, Scalaz._
import argonaut._, Argonaut._
object Mytest extends App {
 val requestJson =
 """
 {
 "userid": "1"
 }
 """.stripMargin
 val updatedJson: Option[Json] = for {
 parsed <- requestJson.parseOption
 } yield ("name", jString("testuser")) ->: parsed
 val obj = updatedJson.get.obj
 printf("Updated user: %s\n", updatedJson.toString())
 printf("obj : %s\n", obj.toString())
 printf("userid: %s\n", obj.get.toMap("userid"))
}

And then

$ sbt
> run
Updated user: Some({"userid":"1","name":"testuser"})
obj : Some(object[("userid","1"),("name","testuser")])
userid: "1"

Make sure you are familiar with Option which is just a value that can also be null (null safe I guess). Argonaut makes use of Scalaz so if you see something you don't understand like the symbol \/ (an or operation) it's probably Scalaz.

answered Nov 21, 2013 at 12:46

Comments

2

You can try this: https://github.com/momodi/Json4Scala

It's simple, and has only one scala file with less than 300 lines code.

There are samples:

test("base") {
 assert(Json.parse("123").asInt == 123)
 assert(Json.parse("-123").asInt == -123)
 assert(Json.parse("111111111111111").asLong == 111111111111111l)
 assert(Json.parse("true").asBoolean == true)
 assert(Json.parse("false").asBoolean == false)
 assert(Json.parse("123.123").asDouble == 123.123)
 assert(Json.parse("\"aaa\"").asString == "aaa")
 assert(Json.parse("\"aaa\"").write() == "\"aaa\"")
 val json = Json.Value(Map("a" -> Array(1,2,3), "b" -> Array(4, 5, 6)))
 assert(json("a")(0).asInt == 1)
 assert(json("b")(1).asInt == 5)
}
test("parse base") {
 val str =
 """
 {"int":-123, "long": 111111111111111, "string":"asdf", "bool_true": true, "foo":"foo", "bool_false": false}
 """
 val json = Json.parse(str)
 assert(json.asMap("int").asInt == -123)
 assert(json.asMap("long").asLong == 111111111111111l)
 assert(json.asMap("string").asString == "asdf")
 assert(json.asMap("bool_true").asBoolean == true)
 assert(json.asMap("bool_false").asBoolean == false)
 println(json.write())
 assert(json.write().length > 0)
}
test("parse obj") {
 val str =
 """
 {"asdf":[1,2,4,{"bbb":"ttt"},432]}
 """
 val json = Json.parse(str)
 assert(json.asMap("asdf").asArray(0).asInt == 1)
 assert(json.asMap("asdf").asArray(3).asMap("bbb").asString == "ttt")
}
test("parse array") {
 val str =
 """
 [1,2,3,4,{"a":[1,2,3]}]
 """
 val json = Json.parse(str)
 assert(json.asArray(0).asInt == 1)
 assert(json(4)("a")(2).asInt == 3)
 assert(json(4)("a")(2).isInt)
 assert(json(4)("a").isArray)
 assert(json(4)("a").isMap == false)
}
test("real") {
 val str = "{\"styles\":[214776380871671808,214783111085424640,214851869216866304,214829406537908224],\"group\":100,\"name\":\"AO4614【金宏达电子】现货库存 质量保证 欢迎购买@\",\"shopgrade\":8,\"price\":0.59,\"shop_id\":60095469,\"C3\":50018869,\"C2\":50024099,\"C1\":50008090,\"imguri\":\"http://img.geilicdn.com/taobao10000177139_425x360.jpg\",\"cag\":50006523,\"soldout\":0,\"C4\":50006523}"
 val json = Json.parse(str)
 println(json.write())
 assert(json.asMap.size > 0)
}
answered Oct 29, 2015 at 2:03

1 Comment

I like this - excellent for small use cases - no need for any libraries.
2

I use uPickle which has the big advantage that it will handle nested case classes automatically:

object SerializingApp extends App {
 case class Person(name: String, address: Address)
 case class Address(street: String, town: String, zipCode: String)
 import upickle.default._
 val john = Person("John Doe", Address("Elm Street 1", "Springfield", "ABC123"))
 val johnAsJson = write(john)
 // Prints {"name":"John Doe","address":{"street":"Elm Street 1","town":"Springfield","zipCode":"ABC123"}}
 Console.println(johnAsJson)
 // Parse the JSON back into a Scala object
 Console.println(read[Person](johnAsJson)) 
}

Add this to your build.sbt to use uPickle:

libraryDependencies += "com.lihaoyi" %% "upickle" % "0.4.3"
ari gold
2,0943 gold badges25 silver badges51 bronze badges
answered Dec 31, 2016 at 13:29

Comments

0

I use PLAY JSON library you can find the mavn repo for only the JSON library not the whole framework here

 val json = "com.typesafe.play" %% "play-json" % version
 val typesafe = "typesafe.com" at "http://repo.typesafe.com/typesafe/releases/"

A very good tutorials about how to use them, are available here:

http://mandubian.com/2012/09/08/unveiling-play-2-dot-1-json-api-part1-jspath-reads-combinators/

http://mandubian.com/2012/10/01/unveiling-play-2-dot-1-json-api-part2-writes-format-combinators/

http://mandubian.com/2012/10/29/unveiling-play-2-dot-1-json-api-part3-json-transformers/

answered Feb 14, 2014 at 12:04

1 Comment

JSON Play was already mentioned above.
0

Let me also give you the SON of JSON version:

import nl.typeset.sonofjson._
arr(
 obj(id = 1, name = "John)
 obj(id = 2, name = "Dani)
)
answered Sep 21, 2014 at 10:24

1 Comment

I would love to use this but can't figure out how to add it to my dependencies as it isn't in maven.
0

Play released its module for dealing with JSON independently from Play Framework, Play WS

Made a blog post about that, check it out at http://pedrorijo.com/blog/scala-json/

Using case classes, and Play WS (already included in Play Framework) you case convert between json and case classes with a simple one-liner implicit

case class User(username: String, friends: Int, enemies: Int, isAlive: Boolean)
object User {
 implicit val userJsonFormat = Json.format[User]
}
Matthias Braun
34.7k27 gold badges158 silver badges177 bronze badges
answered Jan 5, 2016 at 20:35

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.