4

I'm writing a library to convert JSON responses from an API for backwards compatibility reasons. And what I need to do is take in arbitrary JSON, and change certain field names. I'm using scala and argonaut, but I don't see any way in the docs or examples of changing the FIELD names, only the values.

Falmarri
  • 47,727
  • 41
  • 151
  • 191

2 Answers2

1

I don't know of a particularly nice way to do this, but it's not too awful to write a helper that will replace a field in an object and then use that in a cursor with withObject:

def renameField(before: JsonField, after: JsonField)(obj: JsonObject) =
  obj(before).map(v => (obj - before) + (after, v)).getOrElse(obj)

Parse.parseOption("""{ "a": { "b": { "c": 1 } } }""").flatMap { json =>
  (json.hcursor --\ "a").withFocus(_.withObject(renameField("b", "z"))).undo
}

This will return Some({"a":{"z":{"c":1}}}) as expected.

Travis Brown
  • 138,631
  • 12
  • 375
  • 680
  • So if I'm reading that correctly, it looks like I have to know the structure of the JSOn beforehand, which I don't necessarily. I just want to rename any fields named "a" to "b" (roughly). I came up with a solution, but it's equally un-nice. – Falmarri Jan 21 '14 at 20:39
1

I ended up folding over the object I need to convert and adding to a map, and then creating a new json object.

val conversionMap = Map("a" -> "b")

Json(
  j.objectOrEmpty.toMap.foldLeft(Map.empty[JsonField, Json]) {
    case (acc, (key, value)) =>
      acc.updated(conversionMap.getOrElse(key, key), j.fieldOrNull(key))
  }.toSeq: _*
)
Falmarri
  • 47,727
  • 41
  • 151
  • 191