Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Gson, how to deserialize array or empty string

I trying to deserialize this json to array of objects:

[{
    "name": "item 1",
    "tags": ["tag1"]
},
{
    "name": "item 2",
    "tags": ["tag1","tag2"]
},
{
    "name": "item 3",
    "tags": []
},
{
    "name": "item 4",
    "tags": ""
}]

My java class looks like this:

public class MyObject
{
    @Expose
    private String name;

    @Expose
    private List<String> tags = new ArrayList<String>();
}

The problem is json's tags property which can be just empty string or array. Right now gson gives me error: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING

How should I deserialize this json?

I do not have any control to this json, it comes from 3rd pary api.

like image 497
devha Avatar asked Nov 10 '22 08:11

devha


1 Answers

I do not have any control to this json, it comes from 3rd pary api.

If you don't have the control over the data, your best solution is to create a custom deserializer in my opinion:

class MyObjectDeserializer implements JsonDeserializer<MyObject> {
    @Override
    public MyObject deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        JsonObject jObj = json.getAsJsonObject();
        JsonElement jElement = jObj.get("tags");
        List<String> tags = Collections.emptyList();
        if(jElement.isJsonArray()) {
            tags = context.deserialize(jElement.getAsJsonArray(), new TypeToken<List<String>>(){}.getType());
        }
        //assuming there is an appropriate constructor
        return new MyObject(jObj.getAsJsonPrimitive("name").getAsString(), tags);
    }
}

What it does it that it checks whether "tags" is a JsonArray or not. If it's the case, it deserializes it as usual, otherwise you don't touch it and just create your object with an empty list.

Once you've written that, you need to register it within the JSON parser:

Gson gson = new GsonBuilder().registerTypeAdapter(MyObject.class, new MyObjectDeserializer()).create();
//here json is a String that contains your input
List<MyObject> myObjects = gson.fromJson(json, new TypeToken<List<MyObject>>(){}.getType());

Running it, I get as output:

MyObject{name='item 1', tags=[tag1]}
MyObject{name='item 2', tags=[tag1, tag2]}
MyObject{name='item 3', tags=[]}
MyObject{name='item 4', tags=[]}
like image 97
Alexis C. Avatar answered Nov 14 '22 22:11

Alexis C.