Reputation: 1223
Using the CIRCE library & Cats, it would be incredibly useful to be able to transform all the string
values of an arbitrary Json object such as
{
"topLevelStr" : "topLevelVal",
"topLevelInt" : 123,
"nested" : { "nestedStr" : "nestedVal" },
"array" : [
{ "insideArrayStr" : "insideArrayVal1", "insideArrayInt" : 123},
{ "insideArrayStr" : "insideArrayVal2", "insideArrayInt" : 123}
]
}
Is it possble to transform all string values (topLevelVal, nestedVal, insideArrayVal1, insideArrayVal2)
to upper case (or any arbitrary string transformation for that matter)?
Upvotes: 4
Views: 1428
Reputation: 73
If you need to transform just the values, not the keys, you can use:
def transform(fn: String => String)(json: Json): Json =
json
.mapString(fn)
.mapArray(_.map(transform(fn)))
.mapObject(_.mapValues(transform(fn)))
However, be aware that the function is recursive.
Upvotes: 2
Reputation: 4515
You can write recursive function by yourself. It should be something like that:
import io.circe.{Json, JsonObject}
import io.circe.parser._
def transform(js: Json, f: String => String): Json = js
.mapString(f)
.mapArray(_.map(transform(_, f)))
.mapObject(obj => {
val updatedObj = obj.toMap.map {
case (k, v) => f(k) -> transform(v, f)
}
JsonObject.apply(updatedObj.toSeq: _*)
})
val jsonString =
"""
|{
|"topLevelStr" : "topLevelVal",
|"topLevelInt" : 123,
| "nested" : { "nestedStr" : "nestedVal" },
| "array" : [
| {
| "insideArrayStr" : "insideArrayVal1",
| "insideArrayInt" : 123
| }
| ]
|}
""".stripMargin
val json: Json = parse(jsonString).right.get
println(transform(json, s => s.toUpperCase))
Upvotes: 4