I have this json, I've been parsing and replacing fields with json4s, the json looks like this:
{
"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": ""
}
]
}
]
}
The second array called "fields", that's the one I want to replace the empty strings with actual string values. I have been doing this with json4s transformField function, by first parsing the json into a JObject, then transforming the JObject with the new values.
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")) }
}
}
Now I got my original parsed json "a", and I got my new JArray with the updated fields in "v". The last thing I need to do is to merge the new values into the original JObject "a". I tried this with replace, with no luck.
val merged = a.replace(List("fields"), v)
Question:
Here is a runnable version of the code in it's entirety with example prints of the json as well: http://pastebin.com/e0xmxqFF
Since you are very specific about the field you want to update I think the most straightforward solution would be to use mapField
:
val merged = a mapField {
case ("signatories", JArray(arr)) => ("signatories", JArray(arr.updated(1, JObject(JField("fields", v)))))
case other => other
}
replace
can't be used as far as I can see, since you would need to pass it an index, which would not work, since replace
expects its first argument to be a List of fields name.