add field conditionally after traversing all nodes in JSON Circe Scala

374 Views Asked by At

Assume I have a complex JSON:

{
  "type": "object",
  "properties": {
    "first_name": { "type": "string" },
    "last_name": { "type": "string" },
    "birthday": { "type": "string", "format": "date" },
    "address": {
      "type": "object",
      "properties": {
        "street_address": { "type": "string" },
        "city": { "type": "string" },
        "state": { "type": "string" },
        "country": { "type" : "string" }
      }
    }
  }
}

I want to add the field additionalProperties: false to all the json objects having type:object In the above example, the output json would look like:

{
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "first_name": { "type": "string" },
    "last_name": { "type": "string" },
    "birthday": { "type": "string", "format": "date" },
    "address": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "street_address": { "type": "string" },
        "city": { "type": "string" },
        "state": { "type": "string" },
        "country": { "type" : "string" }
      }
    }
  }
}

This is what I have so far:

val circeJson: io.circe.Json = parser.parse(json).getOrElse(io.circe.Json.Null)
    val updatedJson = transform(circeJson)

def transform(js: io.circe.Json): io.circe.Json =
    js
      .mapArray(_.map(transform))
      .mapObject(obj => obj.+:("additionalProperties", io.circe.Json.fromBoolean(false)))

From some reason, it's working and adding the field only for the root level object.

1

There are 1 best solutions below

0
On BEST ANSWER

The following is working:

 def transformJson(js: io.circe.Json, transformation: JsonObject => JsonObject): io.circe.Json =
    js
      .mapArray(_.map(transformJson(_, transformation)))
      .mapObject(obj => transformation(obj).mapValues(obj => transformJson(obj, transformation)))

 val circeJson: io.circe.Json = parser.parse(json).getOrElse(io.circe.Json.Null)
 val updatedJson =
      transformJson(circeJson, obj => obj.+:("additionalProperties", io.circe.Json.fromBoolean(false)))