使用 play-json-extensions 在 json 反序列化后添加附加字段
Add additional fields after de-serialization of json using play-json-extensions
我有一个案例 class 有超过 22 个参数。
case class Model(a1: Int,
a2: Int,
a3: Int,
a4: Int,
a5: Int,
a6: Int,
a7: Int,
a8: Int,
a9: Int,
a10: Int,
a11: Int,
a12: Int,
a13: Int,
a14: Int,
a15: Int,
a16: Int,
a17: Int,
a18: Int,
a19: Int,
a20: Int,
a21: Int,
a22: Int,
a23: Int,
a24: Int)
我收到一个 json 输入,我需要将其反序列化为上述 Model
案例 class。但是,我的输入 json 不包含字段 a1 和 a2。我的 json 看起来像这样
{
"a3": 3,
"a4": 4,
"a5": 5,
"a6": 6,
"a7": 7,
"a8": 8,
"a9": 9,
"a10": 10,
"a11": 11,
"a12": 12,
"a13": 13,
"a14": 14,
"a15": 15,
"a16": 16,
"a17": 17,
"a18": 18,
"a19": 19,
"a20": 20,
"a21": 21,
"a22": 22,
"a23": 23,
"a24": 24
}
现在,为了迎合这种情况,我编写了我的自定义 json reader,它会为 json.[=21 中的字段 a1 和 a2 添加一些虚拟值=]
我有一个自定义方法可以将字段添加到读取的输入 json 中。扩展方法addField
如下
implicit class ReadOps[A](reads: Reads[A]) {
def addField(fieldName: String, value: Int): Reads[A] = Reads {
json: JsValue =>
json
.validate(__.json.update((__ \ fieldName).json.put(JsString(value.toString))))
.map(_.asInstanceOf[A])
}
}
我隐含的json格式如下
implicit val jsonFormat = new OFormat[Model] {
override def reads(json: JsValue): JsResult[Model] = {
Jsonx.formatCaseClass[Model].addField("a1",1).addField("a2",2).reads(json)
}
override def writes(o: Model): JsObject = {
Jsonx.formatCaseClass[Model].writes(o)
}
}
我面临的问题
尽管调用了方法 addField 两次(我试图添加值为 1 的 a1 和值为 2 的 a2),但只有字段 a1
和值 1
被添加到 json 和 a2 被忽略。并且 json 不会反序列化为模型案例 class.
我正在使用以下依赖项
libraryDependencies += "ai.x" %% "play-json-extensions" % "0.30.1"
请告诉我这种方法哪里出了问题。任何指针都会非常有帮助。提前致谢!!!
注意:- 请不要建议在模型案例中添加 a1 和 a2 作为字段的解决方案 class。这是不可能的,因为我的实际问题非常复杂,Whosebug 上的这个问题是手头问题的一个非常简化的版本。
考虑 adding a field in a new branch via JsPath.update
:
val js = Json.obj("key1" -> "value1", "key2" -> "value2")
js.validate(__.json.update((__ \ 'key3).json.put(JsString("value3"))))
=> JsSuccess({"key1":"value1","key2":"value2","key3":"value3"},)
这是一个工作示例
import ai.x.play.json.Jsonx
import play.api.libs.json.Json
import play.api.libs.json._
case class Foo(a1: Int, a2: Int, a3: Int, a4: Int, a5: Int, a6: Int, a7: Int, a8: Int, a9: Int, a10: Int, a11: Int, a12: Int, a13: Int, a14: Int, a15: Int, a16: Int, a17: Int, a18: Int, a19: Int, a20: Int, a21: Int, a22: Int, a23: Int, a24: Int)
object Foo {
implicit val format = Jsonx.formatCaseClass[Foo]
}
object AddFieldsToDeserialisation extends App {
val raw =
"""
|{
| "a3": 3,
| "a4": 4,
| "a5": 5,
| "a6": 6,
| "a7": 7,
| "a8": 8,
| "a9": 9,
| "a10": 10,
| "a11": 11,
| "a12": 12,
| "a13": 13,
| "a14": 14,
| "a15": 15,
| "a16": 16,
| "a17": 17,
| "a18": 18,
| "a19": 19,
| "a20": 20,
| "a21": 21,
| "a22": 22,
| "a23": 23,
| "a24": 24
|}
""".stripMargin
val json = Json.parse(raw)
val updatePutTransformation =
(field: String, value: Int) => __.json.update((__ \ field ).json.put(JsNumber(value)))
val addedFields =
List("a1" -> 1, "a2" -> 2)
.map { case (field, value) => updatePutTransformation(field, value) }
.reduce((putUpdate1, putUpdate2) => putUpdate1 andThen putUpdate2 )
val jsonWithPutValue = json.transform(addedFields)
println(jsonWithPutValue.get)
println(jsonWithPutValue.get.as[Foo])
}
应该输出
{ "a1": 1, "a2": 2, "a3": 3, "a4": 4, "a5": 5, "a6": 6, "a7": 7, "a8": 8, "a9": 9, "a10": 10, "a11": 11, "a12": 12, "a13": 13, "a14": 14, "a15": 15, "a16": 16, "a17": 17, "a18": 18, "a19": 19, "a20": 20, "a21": 21, "a22": 22, "a23": 23, "a24": 24 }
Foo(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24)
我有一个案例 class 有超过 22 个参数。
case class Model(a1: Int,
a2: Int,
a3: Int,
a4: Int,
a5: Int,
a6: Int,
a7: Int,
a8: Int,
a9: Int,
a10: Int,
a11: Int,
a12: Int,
a13: Int,
a14: Int,
a15: Int,
a16: Int,
a17: Int,
a18: Int,
a19: Int,
a20: Int,
a21: Int,
a22: Int,
a23: Int,
a24: Int)
我收到一个 json 输入,我需要将其反序列化为上述 Model
案例 class。但是,我的输入 json 不包含字段 a1 和 a2。我的 json 看起来像这样
{
"a3": 3,
"a4": 4,
"a5": 5,
"a6": 6,
"a7": 7,
"a8": 8,
"a9": 9,
"a10": 10,
"a11": 11,
"a12": 12,
"a13": 13,
"a14": 14,
"a15": 15,
"a16": 16,
"a17": 17,
"a18": 18,
"a19": 19,
"a20": 20,
"a21": 21,
"a22": 22,
"a23": 23,
"a24": 24
}
现在,为了迎合这种情况,我编写了我的自定义 json reader,它会为 json.[=21 中的字段 a1 和 a2 添加一些虚拟值=]
我有一个自定义方法可以将字段添加到读取的输入 json 中。扩展方法addField
如下
implicit class ReadOps[A](reads: Reads[A]) {
def addField(fieldName: String, value: Int): Reads[A] = Reads {
json: JsValue =>
json
.validate(__.json.update((__ \ fieldName).json.put(JsString(value.toString))))
.map(_.asInstanceOf[A])
}
}
我隐含的json格式如下
implicit val jsonFormat = new OFormat[Model] {
override def reads(json: JsValue): JsResult[Model] = {
Jsonx.formatCaseClass[Model].addField("a1",1).addField("a2",2).reads(json)
}
override def writes(o: Model): JsObject = {
Jsonx.formatCaseClass[Model].writes(o)
}
}
我面临的问题
尽管调用了方法 addField 两次(我试图添加值为 1 的 a1 和值为 2 的 a2),但只有字段 a1
和值 1
被添加到 json 和 a2 被忽略。并且 json 不会反序列化为模型案例 class.
我正在使用以下依赖项
libraryDependencies += "ai.x" %% "play-json-extensions" % "0.30.1"
请告诉我这种方法哪里出了问题。任何指针都会非常有帮助。提前致谢!!!
注意:- 请不要建议在模型案例中添加 a1 和 a2 作为字段的解决方案 class。这是不可能的,因为我的实际问题非常复杂,Whosebug 上的这个问题是手头问题的一个非常简化的版本。
考虑 adding a field in a new branch via JsPath.update
:
val js = Json.obj("key1" -> "value1", "key2" -> "value2") js.validate(__.json.update((__ \ 'key3).json.put(JsString("value3")))) => JsSuccess({"key1":"value1","key2":"value2","key3":"value3"},)
这是一个工作示例
import ai.x.play.json.Jsonx
import play.api.libs.json.Json
import play.api.libs.json._
case class Foo(a1: Int, a2: Int, a3: Int, a4: Int, a5: Int, a6: Int, a7: Int, a8: Int, a9: Int, a10: Int, a11: Int, a12: Int, a13: Int, a14: Int, a15: Int, a16: Int, a17: Int, a18: Int, a19: Int, a20: Int, a21: Int, a22: Int, a23: Int, a24: Int)
object Foo {
implicit val format = Jsonx.formatCaseClass[Foo]
}
object AddFieldsToDeserialisation extends App {
val raw =
"""
|{
| "a3": 3,
| "a4": 4,
| "a5": 5,
| "a6": 6,
| "a7": 7,
| "a8": 8,
| "a9": 9,
| "a10": 10,
| "a11": 11,
| "a12": 12,
| "a13": 13,
| "a14": 14,
| "a15": 15,
| "a16": 16,
| "a17": 17,
| "a18": 18,
| "a19": 19,
| "a20": 20,
| "a21": 21,
| "a22": 22,
| "a23": 23,
| "a24": 24
|}
""".stripMargin
val json = Json.parse(raw)
val updatePutTransformation =
(field: String, value: Int) => __.json.update((__ \ field ).json.put(JsNumber(value)))
val addedFields =
List("a1" -> 1, "a2" -> 2)
.map { case (field, value) => updatePutTransformation(field, value) }
.reduce((putUpdate1, putUpdate2) => putUpdate1 andThen putUpdate2 )
val jsonWithPutValue = json.transform(addedFields)
println(jsonWithPutValue.get)
println(jsonWithPutValue.get.as[Foo])
}
应该输出
{ "a1": 1, "a2": 2, "a3": 3, "a4": 4, "a5": 5, "a6": 6, "a7": 7, "a8": 8, "a9": 9, "a10": 10, "a11": 11, "a12": 12, "a13": 13, "a14": 14, "a15": 15, "a16": 16, "a17": 17, "a18": 18, "a19": 19, "a20": 20, "a21": 21, "a22": 22, "a23": 23, "a24": 24 }
Foo(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24)