1

Given a JSON array like this one:

{
    "success": true,
    "data": [
        {
            "id": 600,
            "title": "test deal",
            "e54cbe3a434d8e6": 54
        },
        {
            "id": 600,
            "title": "test deal",
            "e54cbe3a434d8e6": 54
        },
    ],
    "additional_data": {
        "pagination": {
            "start": 0,
            "limit": 100,
            "more_items_in_collection": false
        }
    }
}

In my Play 2.2.2 application, using the Scala JSON Reads Combinator, everything works going this way:

implicit val entityReader = Json.reads[Entity]

  val futureJson: Future[List[Entity]] = futureResponse.map(
    response => (response.json \ "data").validate[List[Entity]].get

The problem now is the key named 'e54cbe3a434d8e6' which I would like to name 'value' in my object:

// This doesn't work, as one might expect
case class Entity(id: Long, title: String, e54cbe3a434d8e6: Long)

// I would like to use 'value' instead of 'e54cbe3a434d8e6'
case class Entity(id: Long, title: String, value: Long)

There is vast information about the combinators here and here but I only want to use a fieldname which is different from the key name in the JSON array. Can some one help me to find a simple way? I suppose it has got something to do with JSON.writes?!

1 Answer 1

3

One simple way without trying to apply transformations on json itself is to define a custom Reads in such a way to handle this:

val json = obj(
  "data" -> obj(
    "id" -> 600, 
    "title" -> "test deal", 
    "e54cbe3a434d8e6" -> 54))

case class Data(id: Long, title: String, value: Int)

val reads = (
  (__ \ "id").read[Long] ~
  (__ \ "title").read[String] ~
  (__ \ "e54cbe3a434d8e6").read[Int] // here you get mapping from your json to Scala case class
)(Data) 

def index = Action {
  val res = (json \ "data").validate(reads)
  println(res) // prints "JsSuccess(Data(600,test deal,54),)"
  Ok(json)
}

Another way is to use combinators like this:

... the same json and case class

implicit val generatedReads = reads[Data]

def index = Action {

  val res = (json \ "data").validate(
    // here we pick value at 'e54cbe3a434d8e6' and put into brand new 'value' branch
    __.json.update((__ \ "value").json.copyFrom((__ \ "e54cbe3a434d8e6").json.pick)) andThen 

    // here we remove 'e54cbe3a434d8e6' branch
    (__ \ "e54cbe3a434d8e6").json.prune andThen 

    // here we validate result with generated reads for our case class
    generatedReads) 

  println(res) // prints "JsSuccess(Data(600,test deal,54),/e54cbe3a434d8e6/e54cbe3a434d8e6)"
  Ok(prettyPrint(json))
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.