单属性样例类Resident的JSON格式化最简实现方法咨询
解决单属性样例类的JSON格式化器最简写法
我完全懂你遇到的这个痛点——单属性样例类用Play JSON的FunctionalBuilder确实会有点反直觉,常规的多参数写法套过来会卡壳,反而要写更多代码。下面给你几种最简的解决方案,按推荐程度排序:
1. 自动派生格式化器(最省心)
如果你的项目允许使用Play JSON的自动派生功能,这绝对是最简的方式,两行代码搞定所有:
import play.api.libs.json._ case class Location(lat: Double, long: Double) case class Resident(location: Location) // 先自动生成Location的格式化器 implicit val locationFormat: Format[Location] = Json.format[Location] // 再自动生成Resident的格式化器,会自动复用上面的locationFormat implicit val residentFormat: Format[Resident] = Json.format[Resident]
Play JSON会自动根据样例类的结构推导读写逻辑,不管是单属性还是多属性都能完美适配,完全不用自己手动拼接路径。
2. 简化FunctionalBuilder写法(适配你的需求)
如果你一定要用FunctionalBuilder的思路,不用自动派生,那可以换用inmap方法来简化单属性的转换,避免多参数的语法糖陷阱:
import play.api.libs.json._ case class Location(lat: Double, long: Double) case class Resident(location: Location) implicit val locationFormat: Format[Location] = Json.format[Location] val residentFormats: Format[Resident] = (JsPath \ "location").format[Location] .inmap(Resident.apply, unlift(Resident.unapply))
这里的inmap可以直接把Location的Format转换成Resident的Format,因为我们只需要把读取到的Location传给Resident.apply,反序列化时把Resident拆解成Location就行,比你原来尝试的写法简洁多了。
3. 手动实现Reads和Writes(不推荐,代码量多)
当然你也可以手动分开写Reads和Writes,但正如你说的,代码量会远超预期,这里只做参考:
import play.api.libs.json._ case class Location(lat: Double, long: Double) case class Resident(location: Location) implicit val locationFormat: Format[Location] = Json.format[Location] implicit val residentReads: Reads[Resident] = (JsPath \ "location").read[Location].map(Resident.apply) implicit val residentWrites: Writes[Resident] = Writes[Resident](res => Json.obj("location" -> Json.toJson(res.location))) implicit val residentFormat: Format[Resident] = Format(residentReads, residentWrites)
这种方式完全手动控制读写逻辑,但单属性场景下没必要这么麻烦,前面两种方法足够高效。
内容的提问来源于stack exchange,提问作者ivanorone
相关产品推荐
相关产品推荐

