简体   繁体   中英

Exclude null values from dynamic nested json using GSON Retrofit in Android

I'm parsing dynamic nested json using gson and Retrofit in Android. I want to exclude null/empty values before I add it to the list.

I've tried the following methods but none of them seem to work:

 // retMap.values().removeIf(Objects::isNull);
 //  Collection<POJOContent> values = retMap.values();
//  while (values.remove(null)) {}

//list.removeAll(Arrays.asList(""));

CustomDeserialiser.java

public class CustomDeserializer implements JsonDeserializer<MyContentWrapper> {
    private final String abc_key = "abc";

    @Override
    public MyContentWrapper deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {


        MyContentWrapper abc = new MyContentWrapper();
        JsonObject object = json.getAsJsonObject().getAsJsonObject(abc_key);
        List<POJOContent> list = new ArrayList<POJOContent>();
        System.out.println("New Data: "+object);

        for (Map.Entry<String, JsonElement> set : object.entrySet()) {
            System.out.println("LIST " + set);

            JsonObject nextObject = object.getAsJsonObject().getAsJsonObject(set.getKey());


           Map<String, POJOContent> retMap = new Gson().fromJson(nextObject, new TypeToken<LinkedHashMap<String, POJOContent>>() {
            }.getType());

            // retMap.values().removeIf(Objects::isNull);
              //  Collection<POJOContent> values = retMap.values();
              //  while (values.remove(null)) {}

                         list.addAll(retMap.values());
                //list.removeAll(Arrays.asList(""));
        
          

        }
        abc.abc = list;
        return abc;
    }

POJOContent.java

        
public class POJOContent {

    @SerializedName("ab")
    public String content;

    @SerializedName("id")
    public String id;

    @SerializedName("key")
    public String key;

    @Override
    public String toString() {
        return content;
    }

    //getters and setters

}

MyContentWrapper.java

public class MyContentWrapper {

    public List<POJOContent> abc;
}

JSON:

{
    "abc": {
        "1": {
            "1": {
                "ab": "some content",
                "id": "240",
                "key": "value"
            },
            "2": {
                "ab": "some content",
                "id": "240",
                "key": "value"
            },
            "3": {
                "ab": "some content",
                "id": "240",
                "key": "value"
            }
        },
        "2": {
            "1": {
                "ab": "some content",
                "id": "241",
                "key": "value"
            },
            "2": {
                "ab": "some content",
                "id": "241",
                "key": "value"
            },
            "3": {
                "ab": "some content",
                "id": "241",
                "key": "value"
            }
        },
        "3": {
            "1": {
                "ab": "",
                "id": "252",
                "key": "value"
            },
            "2": {
                "ab": "some content",
                "id": "252",
                "key": "value"
            },
            "3": {
                "ab": "",
                "id": "252",
                "key": "value"
            }
        }
    }
}

Basically, I want to skip the objects whose "ab" value is empty and NOT add them to the list (the other keys are irrelevant if the "ab" value is empty). To clarify, if the parent object has any child object with "ab" key empty value, the child object should be excluded. If the parent object has all children whose "ab" key has empty values, it should exclude the parent object.

Am I missing something? Would appreciate some help.

EDIT:: Expected JSON:

{
    "abc": {
        "1": {
            "1": {
                "ab": "some content",
                "id": "240",
                "key": "value"
            },
            "2": {
                "ab": "some content",
                "id": "240",
                "key": "value"
            },
            "3": {
                "ab": "some content",
                "id": "240",
                "key": "value"
            }
        },
        "2": {
            "1": {
                "ab": "some content",
                "id": "241",
                "key": "value"
            },
            "2": {
                "ab": "some content",
                "id": "241",
                "key": "value"
            },
            "3": {
                "ab": "some content",
                "id": "241",
                "key": "value"
            }
        },
        "3": {
            "2": {
                "ab": "some content",
                "id": "252",
                "key": "value"
            }
        }
    }
}

UPDATE 2:

This is the response I'm getting after changing List to Maps:

        Callback<MyContentWrapper> myCallback = new Callback<MyContentWrapper>() {
        @Override
        public void onResponse(Call<MyContentWrapper> call, Response<MyContentWrapper> response) {
            if (response.isSuccessful()) {
                Log.d("Callback", " Message: " + response.raw());
                Log.d("Callback", " Message: " + response.body().abc.values());
                still showing empty brackets here --->  
//Log.d =     Message: [{1=1. some content, 1=2. some content, 1=3. some content}, {}]
            } else {
                Log.d("Callback", "Code: " + response.code() + " Message: " + response.message());
            }
        }
        @Override
        public void onFailure(Call<MyContentWrapper> call, Throwable t) {
            t.printStackTrace();
        }
    };

Just for context, this is the JSON response to above the callback:


{
    "abc": {
        "1": {
            "1": {
                "ab": "some content",
                "id": "240",
                "key": "value"
            },
            "2": {
        "ab": "some content",
        "id": "240",
        "key": "value"
            },
      "3": {
        "ab": "some content",
        "id": "240",
        "key": "value"
            }
        },
        "2": {
            "1": {
          "ab": "",
          "id": "241",
          "key": "value"
            },
            "2": {
          "ab": "",
          "id": "241",
          "key": "value"
            },
      "3": {
          "ab": "",
          "id": "241",
          "key": "value"
      }
        }
    }
}

First of all your MyContentWrapper is wrong. It is not a List according to your JSON. It should be map of maps so something like:

public class MyContentWrapper {
    public Map<Integer, Map<Integer, POJOContent>> abc;
}

Now, you could write some complex deserializer for this kind of structure but there is also an another way to do it. Namely, if you declare helper Map like:

@SuppressWarnings("serial")
public class MyMap extends HashMap<Integer, POJOContent> {
    @Override
    public POJOContent put(Integer key, POJOContent value) {
        if(null==value.getContent() || value.getContent().isBlank()) {
            return null;
        }
        // Added only if content = "ab" is not blank.
        return super.put(key, value);
    }
}

and then the tuned MyContentWrapper :

public class MyContentWrapper {
    public Map<Integer, MyMap> abc;
}

Then it is only:

MyContentWrapper mcw = new Gson().fromJson(JSON, MyContentWrapper.class);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM