Search code examples
jsonscalaplayframeworkplayframework-2.0

How to clean a json from empty nested objects and empty arrays


I have a nested object such as:

{ 
  "name:"ABC",
  "nest1":{
     {
       "field1": null,
       "field2": null,
       "field3": [],
       "field4": {},
  },
  "nest2":{
       "field1":"123",
       "field2":null
  }
}

I want to clean this json, and make sure the output will be:

{ 
  "name:"ABC",
  "nest2":{
       "field1":"123"
  }
}

I wrote the following piece of code:

def withoutNullAndEmptyObj(json: JsValue): JsValue = {
  json match {
    case JsObject(fields) =>
      if (fields.isEmpty) JsNull
      else{
        fields.foldLeft(new JsObject(Map()))((agg, field) =>
          field match{
            case (_, JsNull) => agg
            case other@(name, value: JsArray) => if (value == emptyArray) agg else agg+other
            case (name, value: JsObject) => if (value == emptyObject) agg else agg+(name, withoutNullAndEmptyObj(value))
            case other@(name, value) => agg+other
          }
        )
      }
    case other => other
  }
}

The thing is it doesn't fully working. It will produce the following json:

{ 
  "name:"ABC",
  "nest1":{},
  "nest2":{
       "field1":"123"
  }
}

which is not good enough.


Solution

  • With a slight modification to your current code:

    def withoutNullAndEmptyObj(json: JsValue): JsValue = {
      json match {
        case JsObject(fields) =>
          if (fields.isEmpty) JsNull
          else {
            fields.foldLeft(new JsObject(Map()))((agg, field) =>
              field match {
                case (_, JsNull)                    => agg
                case other @ (name, value: JsArray) => if (value == emptyArray) agg else agg + other
                case (name, value: JsObject) => {
                  if (value == emptyObject) agg
                  else {
                    //added further check on else part.
                    val nested = withoutNullAndEmptyObj(value);
                    if (nested == emptyObject)
                      agg
                    else
                      agg + (name, nested)
                  }
                }
                case other @ (name, value) => agg + other
              })
          }
        case other => other
      }
    }