Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Play 2.1 JSON to Scala object

I have a Scala case class

case class Example(name: String, number: Int)

and a companion object

object Example {
  implicit object ExampleFormat extends Format[Example] {
    def reads(json: JsValue) = {
      JsSuccess(Example(
       (json \ "name").as[String],
       (json \ "number").as[Int]))
     }

     def writes(...){}
   }
}

which converts JSON to Scala object.

When JSON is valid (i.e. {"name":"name","number": 0} it works fine. However, when number is in quotes {"name":"name","number":"0"} I get an error: validate.error.expected.jsnumber.

Is there a way to implicitly convert String to Int in such a case (assuming that the number is valid) ?

like image 980
lowercase Avatar asked Jan 27 '13 19:01

lowercase


People also ask

What is the best JSON library for Scala?

Argonaut is a great library. It's by far the best JSON library for Scala, and the best JSON library on the JVM. If you're doing anything with JSON in Scala, you should be using Argonaut. circe is a fork of Argonaut with a few important differences.

What is JSONPath parse?

JSONPath is an expression language to parse JSON data. It's very similar to the XPath expression language to parse XML data. The idea is to parse the JSON data and get the value you want.


1 Answers

You can easily handle this case with the Json combinators, thanks to the orElse helper. I rewrote your json formater with the new syntax introduced by Play2.1

import play.api.libs.json._
import play.api.libs.functional.syntax._

object Example {
  // Custom reader to handle the "String number" usecase
  implicit val reader = (
    (__ \ 'name).read[String] and
    ((__ \ 'number).read[Int] orElse (__ \ 'number).read[String].map(_.toInt))
  )(Example.apply _)

  // write has no specificity, so you can use Json Macro
  implicit val writer = Json.writes[Example] 
}

object Test extends Controller {
  def index = Action {
    val json1 = Json.obj("name" -> "Julien", "number" -> 1000).as[Example]
    val json2 = Json.obj("name" -> "Julien", "number" -> "1000").as[Example]
    Ok(json1.number + " = " + json2.number) // 1000 = 1000
  }
}
like image 190
Julien Lafont Avatar answered Sep 19 '22 13:09

Julien Lafont