I am experimenting with the json4s library (based on lift-json). One of the things I would like to do is to parse a JSON string into an AST, and then manipulate it.
For example, I would like to upsert a field (insert the field into the AST if it does not exist, or update its value if it does).
I have not been able to find how to do it in the documentation. Experimenting with the available methods, I have come up with the following, which works, but feels clumsy.
import org.json4s._
import org.json4s.JsonDSL._
import org.json4s.native.JsonMethods._
object TestJson {
implicit val formats = DefaultFormats
def main(args: Array[String]): Unit = {
val json = """{"foo":1, "bar":{"foo":2}}"""
val ast = parse(json).asInstanceOf[JObject]
println( upsertField(ast, ("foo" -> "3")) )
println( upsertField(ast, ("foobar" -> "3")) )
}
def upsertField(src:JObject, fld:JField): JValue = {
if(src \ fld._1 == JNothing){
src ~ fld
}
else{
src.replace(List(fld._1), fld._2)
}
}
}
I dislike it for many reasons:
- Having to explicitly cast the results of
parse(json)
toJObject
- The result of the
upsertField
function is aJValue
, which I will have to recast if I want to manipulate the object further - The
upsertField
function just feels very unelegant - It does not work for fields that are not at the top level of the hierarchy
Is there a better way to transform the AST?
EDIT: as a workaround to the problem, I have managed to convert my JSON to Scala regular classes, and manipulate them with lenses (Using Lenses on Scala Regular Classes)