代码之家  ›  专栏  ›  技术社区  ›  Dmitry Shkolnik

使用密封的trait/case类玩JSON:无限递归

  •  1
  • Dmitry Shkolnik  · 技术社区  · 8 年前

    我创建了一个简化的示例-如果有人知道如何修复它,请告诉我。

    import play.api.libs.json._
    
    sealed trait Person {
      val name: String
    }
    
    final case class Teacher(name: String, salary: Int) extends Person
    final case class Student(name: String, grade: Int) extends Person
    
    implicit val teacherWrites: Writes[Teacher] = Json.writes[Teacher]
    implicit val studentWrites: Writes[Student] = Json.writes[Student]
    
    val ThePersonWrites: Writes[Person] = Writes(person => {
      Json.writes[Person].writes(person).as[JsObject] - "_type"
    })
    
    implicit val personWrites: Writes[Person] = ThePersonWrites
    
    val people = List[Person] (
      Teacher("Jane Doe", 40000),
      Student("Alice", 5),
      Student("Bob", 7)
      )
    
    Json.prettyPrint(Json.toJson(people))
    
    2 回复  |  直到 8 年前
        1
  •  2
  •   pme    8 年前

    你需要 play-json-derived-codecs

    import play.api.libs.json._
    import julienrf.json.derived
    
    sealed trait Person {
      val name: String
    }
    
    object Person {
      implicit val jsonFormat: OFormat[Person] = derived.oformat[Person]()
    }
    
    final case class Teacher(name: String, salary: Int) extends Person
    final case class Student(name: String, grade: Int) extends Person
    
    
    val people = List[Person] (
      Teacher("Jane Doe", 40000),
      Student("Alice", 5),
      Student("Bob", 7)
    )
    
    println(Json.prettyPrint(Json.toJson(people)))
    

    看到这里了吗 scalafiddle

        2
  •  3
  •   Lasf    8 年前

    这应该做到:

    import play.api.libs.json._
    
    sealed trait Person {
      val name: String
    }
    
    final case class Teacher(name: String, salary: Int) extends Person
    final case class Student(name: String, grade: Int) extends Person
    
    implicit val teacherWrites: Writes[Teacher] = Json.writes[Teacher]
    implicit val studentWrites: Writes[Student] = Json.writes[Student]
    
    implicit val personWrites: Writes[Person] = Writes[Person] {
      case t: Teacher => Json.toJson(t)(teacherWrites)
      case s: Student => Json.toJson(s)(studentWrites)
    }
    
    val people = List[Person] (
      Teacher("Jane Doe", 40000),
      Student("Alice", 5),
      Student("Bob", 7)
    )
    
    Json.prettyPrint(Json.toJson(people))
    

    诀窍是增加 teacherWrites studentWrites 明确地。因为他们都是 Person s、 在它认出他们并给你的朋友打电话之前 personWrites 同样,堆栈溢出。