Official documentation Package documentation
You can use the play json package independently from Play by including
"com.typesafe.play" % "play-json_2.11" % "2.5.3"
in your build.sbt
, see
Overall the easiest way to work with JSON is to have a case class mapping directly to the JSON (same fields name, equivalent types, etc.).
case class Person(
name: String,
age: Int,
hobbies: Seq[String],
pet: Pet
)
case class Pet(
name: String,
`type`: String
)
// these macros will define automatically the conversion to/from JSON
// based on the cases classes definition
implicit val petFormat = Json.format[Pet]
implicit val personFormat = Json.format[Person]
val person = Person(
"Jsony McJsonface",
18,
Seq("Fishing", "Hunting", "Camping"),
Pet("Doggy", "dog")
)
Json.toJson(person).toString
// {"name":"Jsony McJsonface","age":18,"hobbies":["Fishing","Hunting","Camping"],"pet":{"name":"Doggy","type":"dog"}}
val str =
"""{
| "name" : "Jsony McJsonface",
| "age" : 18,
| "hobbies" : [ "Fishing", "Hunting", "Camping" ],
| "pet" : {
| "name" : "Doggy",
| "type" : "dog"
| }
|}""".stripMargin
Json.parse(str).as[Person]
// Person(Jsony McJsonface,18,List(Fishing, Hunting, Camping),Pet(Doggy,dog))
You can build a JSON object tree (a JsValue
) manually
import play.api.libs.json._
val json = JsObject(Map(
"name" -> JsString("Jsony McJsonface"),
"age" -> JsNumber(18),
"hobbies" -> JsArray(Seq(
JsString("Fishing"),
JsString("Hunting"),
JsString("Camping")
))
))
Or with the shorter equivalent syntax, based on a few implicit conversions :
import play.api.libs.json._
val json = Json.obj(
"name" -> "Jsony McJsonface",
"age" -> 18,
"hobbies" -> Seq(
"Fishing",
"Hunting",
"Camping"
)
)
To get the JSON string :
json.toString
// {"name":"Jsony McJsonface","age":18,"hobbies":["Fishing","Hunting","Camping"]}
Json.prettyPrint(json)
// {
// "name" : "Jsony McJsonface",
// "age" : 18,
// "hobbies" : [ "Fishing", "Hunting", "Camping" ]
// }
public Result sayHello() {
JsonNode json = request().body().asJson();
if(json == null) {
return badRequest("Expecting Json data");
} else {
String name = json.findPath("name").textValue();
if(name == null) {
return badRequest("Missing parameter [name]");
} else {
return ok("Hello " + name);
}
}
}
@BodyParser.Of(BodyParser.Json.class)
public Result sayHello() {
JsonNode json = request().body().asJson();
String name = json.findPath("name").textValue();
if(name == null) {
return badRequest("Missing parameter [name]");
} else {
return ok("Hello " + name);
}
}
Hint: The advantage of this way is that Play will automatically respond with an HTTP status code 400 if the request was not a valid one (Content-type was set to application/json
but no JSON was provided)
If you are given a JSON string :
val str =
"""{
| "name" : "Jsony McJsonface",
| "age" : 18,
| "hobbies" : [ "Fishing", "Hunting", "Camping" ],
| "pet" : {
| "name" : "Doggy",
| "type" : "dog"
| }
|}""".stripMargin
You can parse it to get a JsValue, representing the JSON tree
val json = Json.parse(str)
And traverse the tree to lookup specific values :
(json \ "name").as[String] // "Jsony McJsonface"
\
to go to a specific key in a JSON object\\
to go to all occurences of a specific key in a JSON object, searching recursively in nested objects.apply(idx)
(i.e. (idx)
) to go to a index in an array.as[T]
to cast to a precise subtype.asOpt[T]
to attempt to cast to a precise subtype, returning None if it's the wrong type.validate[T]
to attempt to cast a JSON value to a precise subtype, returning a JsSuccess or a JsError(json \ "name").as[String] // "Jsony McJsonface"
(json \ "pet" \ "name").as[String] // "Doggy"
(json \\ "name").map(_.as[String]) // List("Jsony McJsonface", "Doggy")
(json \\ "type")(0).as[String] // "dog"
(json \ "wrongkey").as[String] // throws JsResultException
(json \ "age").as[Int] // 18
(json \ "hobbies").as[Seq[String]] // List("Fishing", "Hunting", "Camping")
(json \ "hobbies")(2).as[String] // "Camping"
(json \ "age").asOpt[String] // None
(json \ "age").validate[String] // JsError containing some error detail