scala json recipes
Own that JSON using the powerful json4s library.
Json examples from json-schema.org.
–
Library dependencies:
(Gradle format)
'org.json4s:json4s-jackson_2.11:3.5.0'
'org.json4s:json4s-ext_2.10:3.5.0'
'org.json4s:json4s-native_2.11:3.5.0'imports:
import org.json4s._
import org.json4s.native.JsonMethods._
import org.json4s.JsonDSL._
// needed for most examples that follow:
implicit val formats = org.json4s.DefaultFormats–
When the top level is a JSON Object:
val jsonString = s"""
  {
    "id": 1,
    "name": "A green door",
    "price": 12.50,
    "tags": ["home", "green"]
  }
"""1. Parse directly into Scala
This is possible with the org.json4s.extract method.
Note that method’s signature:
def extract[A](implicit formats: Formats, mf: scala.reflect.Manifest[A]): Awhich requires an implicit param of type Formats is required.  So be sure to declare an implicit param of that type in scope of the extract call.
Extracting to Map[String, Any] seems to work for most cases:
implicit val formats = org.json4s.DefaultFormats
parse(jsonString).extract[Map[String, Any]]
/*
**  Map(id -> 1, name -> A green door, price -> 12.5, tags -> List(home, green))
*/2. Extract a field using the library DSL
val parsed = parse(jsonString)
parsed \\ "id"
/*
**  JInt(1)
*/
(parsed \\ "id").extract[Int]
/*
**  1
*/
parsed findField {
 case JField("id", _) => true
 case _ => false
}
/*
**  Some((id,JInt(1)))
*/
val wrappedTags = parsed \\ "tags"
wrappedTags.extract[Array[String]].toList
/*
**  List(home, green)
*/3. Extract a field using a case class
Leverage all the power of Scala case classes for working with data.
It is not required that the case class implement all fields of the JSON.
This is my preferred method.
case class Summary(name: String, tags: List[String])
parse(jsonString).extract[Summary]
/*
**  Summary(A green door, List(home, green))
*/
val summary = parse(jsonString).extract[Summary]
summary.name
/*
**  A green door
*/–
When the top level is a JSON Array of Objects:
val setOfProducts = s"""[
  {
      "id": 2,
      "name": "An ice sculpture",
      "price": 12.50,
      "tags": ["cold", "ice"],
      "dimensions": {
          "length": 7.0,
          "width": 12.0,
          "height": 9.5
      }
  },
  {
      "id": 3,
      "name": "A blue mouse",
      "price": 25.50,
      "dimensions": {
          "length": 3.1,
          "width": 1.0,
          "height": 1.0
      }
  }
]"""1. Go for the gold
parse(setOfProducts).extract[List[Map[String, Any]]]
/*
** List(Map(name -> An ice sculpture, tags -> List(cold, ice), price -> 12.5, id -> 2, dimensions -> Map(length -> 7.0, width -> 12.0, height -> 9.5)), Map(id -> 3, name -> A blue mouse, price -> 25.5, dimensions -> Map(length -> 3.1, width -> 1.0, height -> 1.0)))
*/2. Extract a field from each object using a sequence comprehension
val jsonSetOfProducts = parse(setOfProducts)
val names = for {
  JArray(products) <- jsonSetOfProducts
  JObject(product) <- products
  JField("name", JString(name)) <- product
} yield name
/*
**  List(An ice sculpture, A blue mouse)
*/3. Extract using case classes
Again this is the preferred method. Leverage one of Scala’s best features, the case class, and own that JSON!
val jsonSetOfProducts = parse(setOfProducts)
case class ProductName(name: String)
val names = jsonSetOfProducts.extract[List[ProductName]]
/*
**  List(ProductName(An ice sculpture), ProductName(A blue mouse))
*/
case class ProductDimensions(dimensions: Map[String, Double])
val dimes = jsonSetOfProducts.extract[List[ProductDimensions]]
/*
**  List(ProductDimensions(Map(length -> 7.0, width -> 12.0, height -> 9.5)), ProductDimensions(Map(length -> 3.1, width -> 1.0, height -> 1.0)))
*/4. Transform, Find, Filter, RemoveField
jsonSetOfProducts transformField {
  case JField("name", JString(s)) => ("NAME", JString(s.toUpperCase))
}
/*
**  JArray(List(JObject(List((id,JInt(2)), (NAME,JString(AN ICE SCULPTURE)), (price,JDouble(12.5)), (tags,JArray(List(JString(cold), JString(ice)))), (dimensions,JObject(List((length,JDouble(7.0)), (width,JDouble(12.0)), (height,JDouble(9.5))))))), JObject(List((id,JInt(3)), (NAME,JString(A BLUE MOUSE)), (price,JDouble(25.5)), (dimensions,JObject(List((length,JDouble(3.1)), (width,JDouble(1.0)), (height,JDouble(1.0)))))))))
*/
jsonSetOfProducts filterField {
  case JField("name", _) => true
  case _ => false
}
/*
** List((name,JString(An ice sculpture)), (name,JString(A blue mouse)))
*/
jsonSetOfProducts findField {
  case JField("name", _) => true
  case _ => false
}
/*
**  Some((name,JString(An ice sculpture)))
*/
jsonSetOfProducts removeField {
  case JField("dimensions", _) => true
  case _ => false
}
/*
**  JArray(List(JObject(List((id,JInt(2)), (name,JString(An ice sculpture)), (price,JDouble(12.5)), (tags,JArray(List(JString(cold), JString(ice)))))), JObject(List((id,JInt(3)), (name,JString(A blue mouse)), (price,JDouble(25.5))))))
*/