JSONObject remove empty value pairs

22,889

Solution 1

If you use javax.api API:

public static JsonArray removeNull(JsonArray array) {
    JsonArrayBuilder builder = Json.createArrayBuilder();
    int i = 0;
    for (Iterator<JsonValue> it = array.iterator(); it.hasNext(); ++i) {
        JsonValue value = it.next();
        switch (value.getValueType()) {
        case ARRAY:
            JsonArray a = removeNull(array.getJsonArray(i));
            if (!a.isEmpty())
                builder.add(a);
            break;
        case OBJECT:
            JsonObject object = removeNull(array.getJsonObject(i));
            if (!object.isEmpty())
                builder.add(object);
            break;
        case STRING:
            String s = array.getString(i);
            if (s != null && !s.isEmpty())
                builder.add(s);
            break;
        case NUMBER:
            builder.add(array.getJsonNumber(i));
            break;
        case TRUE:
        case FALSE:
            builder.add(array.getBoolean(i));
            break;
        case NULL:
            break;
        }
    }
    return builder.build();
}

public static JsonObject removeNull(JsonObject obj) {
    JsonObjectBuilder builder = Json.createObjectBuilder();
    for (Iterator<Entry<String, JsonValue>> it = obj.entrySet().iterator(); it.hasNext();) {
        Entry<String, JsonValue> e = it.next();
        String key = e.getKey();
        JsonValue value = e.getValue();
        switch (value.getValueType()) {
        case ARRAY:
            JsonArray array = removeNull(obj.getJsonArray(key));
            if (!array.isEmpty())
                builder.add(key, array);
            break;
        case OBJECT:
            JsonObject object = removeNull(obj.getJsonObject(key));
            if (!object.isEmpty())
                builder.add(key, object);
            break;
        case STRING:
            String s = obj.getString(key);
            if (s != null && !s.isEmpty())
                builder.add(key, s);
            break;
        case NUMBER:
            builder.add(key, obj.getJsonNumber(key));
            break;
        case TRUE:
        case FALSE:
            builder.add(key, obj.getBoolean(key));
            break;
        case NULL:
            break;
        }
    }
    return builder.build();
}

@Test
public void testRemoveNullJsonObject() {
    String str = ""
        + "{"
        + "   \"models\":{},"
        + "   \"path\":["
        + "      {"
        + "         \"path\":\"/web-profiles\","
        + "         \"operations\":["
        + "            {"
        + "               \"nickname\":\"CreateAWebExperienceProfile\","
        + "               \"type\":\"\","
        + "               \"responseMessages\":[]"
        + "            }"
        + "         ]"
        + "      }"
        + "   ],"
        + "   \"produces\":[]"
        + "}";
    JsonObject json = Json.createReader(new StringReader(str)).readObject();
    System.out.println(json);
    JsonObject removed = removeNull(json);
    System.out.println(removed);
    // -> {"path":[{"path":"/web-profiles","operations":[{"nickname":"CreateAWebExperienceProfile"}]}]}
}

Solution 2

First, you should deserialize json to a Map<String, Object>. Second, loop the map entry to find out what key has null value or what key has value is instance of ArrayList but empty and remove from the Map. Last, serialize the Map to json.

Try this code:

String json = "{'a': 'apple', 'b': 'ball', 'c': 'cat', 'd': null, 'e': []}";
Type type = new TypeToken<Map<String, Object>>() {}.getType();
Map<String, Object> data = new Gson().fromJson(json, type);

for (Iterator<Map.Entry<String, Object>> it = data.entrySet().iterator(); it.hasNext();) {
    Map.Entry<String, Object> entry = it.next();
    if (entry.getValue() == null) {
        it.remove();
    } else if (entry.getValue() instanceof ArrayList) {
        if (((ArrayList<?>) entry.getValue()).isEmpty()) {
            it.remove();
        }
    }
}

json = new GsonBuilder().setPrettyPrinting().create().toJson(data);
System.out.println(json);

Solution 3

Regex solution

You could use REGEX to remove any line from your data that conatins a "",[],or {} before you parse it with the JSONParser.

The regex for something like this would look like. Keep in mind that you may have to adjust the new line character depending on your OS

[^\n]*(\"(\n)*\"|\[(\n)*\]|\{(\n)*\})[^\n]*

To account for an instance where the JSON data is as follows

{  
   "models":{},
   "path":[  
      {  
         "path":"/web-profiles",
         "operations":[  
            {  
               "nickname":"",
               "type":"",
               "responseMessages":[]
            }
         ]
      }
   ],
   "produces":[]
}

The first time you run that replaceAll it will result with

{  
   "path":[  
      {  
         "path":"/web-profiles",
         "operations":[  
            {  
            }
         ]
      }
   ],
}

Now we an empty JSONObject inside of the "operations" JSONArray. So this replaceAll function needs to be called again untill the JSON String doesn't have any changes from it's previous state.

Keep in mind that if you use functions like readLine() during data input it can remove the newline character which will make this method not work. So solve this replace your read line with this.

json += in.readLine() + '\n';

Here is a quick program I wrote that does the actual removal of empty json objects from the original String.

public static void main(String[] args){
    // String from above example with newline characters intact
    String json = "{\n\"models\":{},\n\"path\":[\n{\n\"path\":\"/web-profiles\",\n\"operations\":[\n{\n\"nickname\":\"\",\n\"type\":\"\",\n\"responseMessages\":[]\n}\n]\n}\n],\n\"produces\":[]\n}";

    // Value from the last iteration of the while loop
    String last = "";
    // If there was no change from the last replaceAll call stop
    while( !last.equals(json) ){
        last = json;
        // Same regex as above just escaped to work in a Java String
        json = json.replaceAll("[^\\n]*(\\{(\\n)*\\}|\\\"(\\n)*\\\"|\\[(\\n)*\\])[^\\n]*\\n","");
    }

    System.out.println(json);
}
Share:
22,889
A Phototactic Coder
Author by

A Phototactic Coder

Updated on November 20, 2020

Comments

  • A Phototactic Coder
    A Phototactic Coder over 3 years

    Here is my Json File:

    {  
       "models":{},
       "path":[  
          {  
             "path":"/web-profiles",
             "operations":[  
                {  
                   "type":"",
                   "responseMessages":[]
                }
             ]
          }
       ],
       "produces":[]
    }
    

    If the values of keys are empty (includes [], "", {}). How can I remove those pairs from Json file.

    1. I tried to use JSONObject build-in functions to remove unnecessary pairs. But, it didn't work.
    2. I tried to use string method to process it line by line. It got too many cases, I can't cover all of those cases in my code. (for example, the sub-key 'operations', when you want to remove all empty value, this key(operations) value pair also should be removed.) Any ideas?
  • Rey Rajesh
    Rey Rajesh about 8 years
    Type, TypeToken, GsonBuilder, Gson.. any jar for these api..?