使用组合器将JSON数组映射到Scala对象时如何使用不同的名称

时间:2014-04-10 13:06:09

标签: json scala playframework

给定像这样的JSON数组:

{
    "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
        }
    }
}

在我的Play 2.2.2应用程序中,使用Scala JSON Reads Combinator,一切都按照这种方式进行:

implicit val entityReader = Json.reads[Entity]

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

现在的问题是名为'e54cbe3a434d8e6'的密钥,我想在我的对象中命名为'value':

// 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)

有关于组合器herehere的大量信息,但我只想使用与JSON数组中的键名不同的字段名。有人可以帮我找一个简单的方法吗? 我想它与JSON.writes有关?!

1 个答案:

答案 0 :(得分:3)

一种不尝试在json上应用转换的简单方法是以这种方式定义自定义读取来处理这个:

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)
}

另一种方法是使用这样的组合器:

... 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))
}