Search code examples
javagsondeserialization

Java ignore custom deserialization on GSON if json format is valid


I have been looking around but could not find any conclusion for my problem, I'll try to describe it the best way I can.

I'm calling an API that can respond 2 ways (note that class names are only examples, not the real names):

Bad response:

{
        "CustomObject_1" : {
            "CustomObject_1.1" : {
                ...
            },
            "CustomObject_1.2" : [
                [ ]
            ]
        },
        "CustomObject_2" : {
            ...
        }

Good response:

{
        "CustomObject_1" : {
            "CustomObject_1.1" : {
                ...
            },
            "CustomObject_1.2" : [
                "CustomObject_1.2.1" : {
                ...
                }
            ]
        },
        "CustomObject_2" : {
            ...
        }

The difference is in CustomObject_1.2 that can be a custom object (that contains more layers of custom objects inside), or it can be an empty array.

I have a deserializer that corrects the bad response, but it makes the good response null, instead of using the default serialization.

class CustomObject_1.2Deserializer

public CustomObject_1.2 deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {
        if (json.isJsonArray()) {
            JsonArray jsonArray = json.getAsJsonArray();
            if (jsonArray.size() == 0) {
                System.out.println(jsonArray);  // return an empty Totals object
                return new CustomObject_1.2();
            }
        } else if (json.isJsonObject()) {
            JsonObject jsonObject = json.getAsJsonObject();
            if (jsonObject.has("CustomObject_1.2.1") && jsonObject.get("CustomObject_1.2.1").isJsonArray()) {
                JsonArray competitorsArray = jsonObject.getAsJsonArray("competitors");
                System.out.println(competitorsArray);   //valid object so use default serialization
            }
        }
        return null;
    }

Is there a way to ignore the deserialization when the json comes as a valid object?

In case it's needed here is the function that handles the gson serialization:

private MyDtoInterface processResponse(String message) {
        MyDtoInterface mDto = null;
        try {
                Gson gson = new GsonBuilder()
                        .registerTypeAdapter(CustomObject_1.2.class, new CustomObject_1.2Deserializer())
                        .create();
                mDto = gson.fromJson(message, CustomparentDTO.class);
        } catch (Exception e) {
            System.out.println("Json format not compatible with ParentDTO");
        }
        return mDto;
    }

Thank you in advance!

I've lost count of what I've tried. And most examples I can find use primitives and not CustomObjects inside CustomObjects.

I was trying to only deserialize the invalid json. If I try to build a new CustomObject_1.2() it will be endless because it's attributes are not primites like String, Integer, Date, ... they are custom objecst inside objects.

The code above will return the following: Bad response (will build a good DTO):

{
        "CustomObject_1" : {
            "CustomObject_1.1" : {
                ...
            },
            "CustomObject_1.2" : [
                "CustomObject_1.2.1" : null
            ]
        },
        "CustomObject_2" : {
            ...
        }

Good response (will build a null DTO):

{
        "CustomObject_1" : {
            "CustomObject_1.1" : {
                ...
            },
            "CustomObject_1.2" : [
                All elements are null
            ]
        },
        "CustomObject_2" : {
            ...
        }

Solution

  • I've changed my deserializer code like below and it looks like it's working like it should, although I'm not sure if it makes sense.

    public CustomObject_1.2 deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {
        if (json.isJsonArray()) {
            JsonArray jsonArray = json.getAsJsonArray();
            if (jsonArray.size() == 0) {
                System.out.println(jsonArray);  // return an empty Totals object
                return new CustomObject_1.2();
            }
        } else if (json.isJsonObject()) {
            JsonObject jsonObject = json.getAsJsonObject();
            if (jsonObject.has("CustomObject_1.2.1") && jsonObject.get("CustomObject_1.2.1").isJsonArray()) {
                JsonArray competitorsArray = jsonObject.getAsJsonArray("competitors");
                System.out.println(competitorsArray);   //valid object so use default serialization
                return new Gson.fromJson(jsonObject, CustomObject_1.2.class);
            }
        }
        return null;
    }