用 json4s.replace 替换 Json AST 中的对象
replace object in Json AST with json4s.replace
我有这个 json,我一直在用 json4s 解析和替换字段,json 看起来像这样:
{
"id": "6988",
"signatories": [
{
"fields": [
{
"name": "fstname",
"value": "Bruce"
},
{
"name": "sndname",
"value": "Lee"
},
{
"name": "email",
"value": "bruce.lee@company.com"
},
{
"name": "sigco",
"value": "Company"
},
{
"name": "mobile",
"value": "0760000000"
}
]
},
{
"fields": [
{
"name": "fstname",
"value": ""
},
{
"name": "sndname",
"value": ""
},
{
"name": "email",
"value": ""
},
{
"name": "mobile",
"value": ""
},
{
"name": "sigco",
"value": ""
}
]
}
]
}
第二个数组称为 "fields",这是我要用实际字符串值替换空字符串的数组。我一直在使用 json4s transformField 函数执行此操作,首先将 json 解析为 JObject,然后使用新值转换 JObject。
val a = parse(json)
// transform the second occurance of fields (fields[1])
val v = a.\("signatories").\("fields")(1).transform {
// Each JArray is made of objects. Find fields in the object with key as name and value as fstname
case obj: JObject => obj.findField(_.equals(JField("name", JString("fstname")))) match {
case None => obj //Didn't find the field. Return the same object back to the array
// Found the field. Change the value
case Some(x) =>
obj.transformField { case JField(k, v) if k == "value" => JField(k, JString("New name")) }
}
}
现在我得到了我的原始解析 json "a",并且我得到了我的新 JArray "v" 中的更新字段。我需要做的最后一件事是将新值合并到原始 JObject "a"。我用替换试过了,没有运气。
val merged = a.replace(List("fields"), v)
问题:
- 如何使用 replace() 替换我第二次出现的字段数组?
- 有更好的方法吗?非常感谢建议。
这是完整代码的可运行版本,其中还包含 json 的打印示例:
http://pastebin.com/e0xmxqFF
由于您对要更新的字段非常具体,我认为最直接的解决方案是使用 mapField
:
val merged = a mapField {
case ("signatories", JArray(arr)) => ("signatories", JArray(arr.updated(1, JObject(JField("fields", v)))))
case other => other
}
replace
据我所知不能使用,因为你需要给它传递一个索引,这是行不通的,因为 replace
期望它的第一个参数是字段名称列表。
我有这个 json,我一直在用 json4s 解析和替换字段,json 看起来像这样:
{
"id": "6988",
"signatories": [
{
"fields": [
{
"name": "fstname",
"value": "Bruce"
},
{
"name": "sndname",
"value": "Lee"
},
{
"name": "email",
"value": "bruce.lee@company.com"
},
{
"name": "sigco",
"value": "Company"
},
{
"name": "mobile",
"value": "0760000000"
}
]
},
{
"fields": [
{
"name": "fstname",
"value": ""
},
{
"name": "sndname",
"value": ""
},
{
"name": "email",
"value": ""
},
{
"name": "mobile",
"value": ""
},
{
"name": "sigco",
"value": ""
}
]
}
]
}
第二个数组称为 "fields",这是我要用实际字符串值替换空字符串的数组。我一直在使用 json4s transformField 函数执行此操作,首先将 json 解析为 JObject,然后使用新值转换 JObject。
val a = parse(json)
// transform the second occurance of fields (fields[1])
val v = a.\("signatories").\("fields")(1).transform {
// Each JArray is made of objects. Find fields in the object with key as name and value as fstname
case obj: JObject => obj.findField(_.equals(JField("name", JString("fstname")))) match {
case None => obj //Didn't find the field. Return the same object back to the array
// Found the field. Change the value
case Some(x) =>
obj.transformField { case JField(k, v) if k == "value" => JField(k, JString("New name")) }
}
}
现在我得到了我的原始解析 json "a",并且我得到了我的新 JArray "v" 中的更新字段。我需要做的最后一件事是将新值合并到原始 JObject "a"。我用替换试过了,没有运气。
val merged = a.replace(List("fields"), v)
问题:
- 如何使用 replace() 替换我第二次出现的字段数组?
- 有更好的方法吗?非常感谢建议。
这是完整代码的可运行版本,其中还包含 json 的打印示例: http://pastebin.com/e0xmxqFF
由于您对要更新的字段非常具体,我认为最直接的解决方案是使用 mapField
:
val merged = a mapField {
case ("signatories", JArray(arr)) => ("signatories", JArray(arr.updated(1, JObject(JField("fields", v)))))
case other => other
}
replace
据我所知不能使用,因为你需要给它传递一个索引,这是行不通的,因为 replace
期望它的第一个参数是字段名称列表。