使用Scala/Play将JSON转换为带有嵌套对象的case类
假设我正在处理的JSON响应的格式如下:使用Scala/Play将JSON转换为带有嵌套对象的case类,json,scala,parsing,playframework,Json,Scala,Parsing,Playframework,假设我正在处理的JSON响应的格式如下: [ { "make": "Tesla", "model": "Model S", "year": 2017, "color": "red", "owner": "Bob", "max_speed": 200, "wheel_size": 30, "is_convertible": true, "license": "ABC
[
{
"make": "Tesla",
"model": "Model S",
"year": 2017,
"color": "red",
"owner": "Bob",
"max_speed": 200,
"wheel_size": 30,
"is_convertible": true,
"license": "ABC123",
"cost": 50000,
"down_payment": 2500,
"other_property_1": 1,
"other_property_2": 2,
"other_property_3": 3,
"other_property_4": 4,
"other_property_5": 5,
"other_property_6": 6,
"other_property_7": 7,
"other_property_8": 8,
"other_property_9": 9,
"other_property_10": 10,
"other_property_11": 11
}
]
这里的JSON是一个car对象数组(为了简单起见,只有1个),我试图使用JSON读取转换器将其转换为一个模型。假设我有一个Car case类来表示每个对象,该类有一个嵌套的FinancialInfo case类来逻辑地分割属性的数量,以避免Scala的22个参数限制
import play.api.libs.functional.syntax._
import play.api.libs.json._
case class Car(
make: String,
model: String,
year: Int,
color: String,
owner: String,
maxSpeed: Int,
wheelSize: Int,
isConvertible: Boolean,
license: String,
financialInfo: FinancialInfo, // nested case class to avoid 22 param limit
otherProperty1: Int,
otherProperty2: Int,
otherProperty3: Int,
otherProperty4: Int,
otherProperty5: Int,
otherProperty6: Int,
otherProperty7: Int,
otherProperty8: Int,
otherProperty9: Int,
otherProperty10: Int,
otherProperty11: Int
)
object Car {
implicit val reads: Reads[Car] = (
(__ \ "make").read[String] and
(__ \ "model").read[String] and
(__ \ "year").read[Int] and
(__ \ "color").read[String] and
(__ \ "owner").read[String] and
(__ \ "max_speed").read[Int] and
(__ \ "wheel_size").read[Int] and
(__ \ "is_convertible").read[Boolean] and
(__ \ "license").read[String] and
(__ \ "financialInfo").read[FinancialInfo] and
(__ \ "other_property_1").read[Int] and
(__ \ "other_property_2").read[Int] and
(__ \ "other_property_3").read[Int] and
(__ \ "other_property_4").read[Int] and
(__ \ "other_property_5").read[Int] and
(__ \ "other_property_6").read[Int] and
(__ \ "other_property_7").read[Int] and
(__ \ "other_property_8").read[Int] and
(__ \ "other_property_9").read[Int] and
(__ \ "other_property_10").read[Int] and
(__ \ "other_property_11").read[Int]
)(Car.apply _)
}
case class FinancialInfo(
cost: BigDecimal,
downPayment: BigDecimal
)
object FinancialInfo {
implicit val reads: Reads[FinancialInfo] = (
(__ \ "cost").read[BigDecimal] and
(__ \ "down_payment").read[BigDecimal]
)(FinancialInfo.apply _)
}
但是,我猜,由于JSON中没有名为financialInfo
的属性,因此无法正确解析它。在我的实际应用程序中,当我使用response.json.validate[List[Car]]
时,会出现此错误:
JsError(List(((0)/financialInfo,List(JsonValidationError(List(error.path.missing),WrappedArray())))))
总之,在示例中,
成本
和首付
不包含在嵌套对象中,即使对于Car case类,我必须包含一个名为financialInfo
的嵌套模型。解决此错误并确保可以解析成本
和首付
的值的最佳方法是什么?任何帮助或见解都将不胜感激 读取
可以组合并包含在彼此中
因此,有:
implicit val fiReads: Reads[FinancialInfo] = (
(JsPath \ "cost").read[BigDecimal] and
(JsPath \ "down_payment").read[BigDecimal]
)(FinancialInfo.apply _)
我们可以将其包含在父级读物中
:
implicit val carReads: Reads[Car] = (
(JsPath \ "make").read[String] and
(JsPath \ "model").read[String] and
fiReads // <--- HERE!
)(Car.apply _)
它被正确解析:
JsSuccess(List(Car(Tesla,Model S,FinancialInfo(50000,2500)), Car(Tesla,Model D,FinancialInfo(30000,1500))),)
p、 s.原始问题中的
读物
,不需要包装到不同的对象
s中。相关的隐式值在同一范围内更好,更接近它们实际使用的位置。你能发布完整的Json和case类吗?试试jsoniter scala:它对字段数量没有这样的限制,非常方便和高效。谢谢!你的解决方案奏效了,我想我是想得太多了。具体地说,将(\uu \“financialInfo”).read[financialInfo]
替换为financialInfo.reads
,修复了我的示例
JsSuccess(List(Car(Tesla,Model S,FinancialInfo(50000,2500)), Car(Tesla,Model D,FinancialInfo(30000,1500))),)