You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

单属性样例类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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 07:46:20