简体   繁体   中英

How to define a `Write` for an case class which will generate nested custom fields?

Play framework provided some DSL to read and write JSON, eg

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

case class User(name:String, age:Option[Int])

implicit val userWrites = (
  (__ \ "name" ).write[String] and
  (__ \ "age"  ).writeNullable[Int]
  )(unlift(User.unapply))

val user= new User("Freewind", Some(100))
Json.toJson(user)

It will generate a json:

{"name":"Freewind","age":100}

But how to define the userWrites to generate such a JSON:

{
   "name" : "Freewind",
   "age"  : 100,
   "nested" : {
       "myname" : "Freewind",
       "myage"  :  100
   }
}

I tried some solutions but none can work.

You can achieve that with JSON transformers , like in this code:

object Test {

  def main(args: Array[String]): Unit = {

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

    case class User(name: String, age: Option[Int])

    implicit val userWrites = (
      (__ \ "name").write[String] and
      (__ \ "age").writeNullable[Int])(unlift(User.unapply))

    val jsonTransformer = (__).json.update(
      __.read[JsObject].map { o => o ++ Json.obj("nested" -> Json.obj()) }) and
      (__ \ 'nested).json.copyFrom((__).json.pick)      reduce

    val user = new User("Freewind", Some(100))
    val originalJson = Json.toJson(user)
    println("Original: " + originalJson)
    val transformedJson = originalJson.transform(jsonTransformer).get
    println("Tansformed: " + transformedJson)

  }

}

The output would be this:

Original: {"name":"Freewind","age":100}

Tansformed: {"name":"Freewind","age":100,"nested":{"name":"Freewind","age":100}}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM