Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deserialize nested object with GSON

I'm trying to deserialize the following structure

{ meta: { keywords:  [a, b, c, d]}  ...  }

other valid structures are

{ meta: { keywords: "a,b,c,d"}  ... }

and

{ meta: {keywords: "a"}  ...}

I have this classes

public class Data {
   @PropertyName("meta")
   MetaData meta;
   ...
}


public class  MetaData {
    List<String> keywords;
    ...
}

and a custom deserializer

public static class CustomDeserilizer implements JsonDeserializer<MetaData>{
    @Override
    public MetaData deserialize(JsonElement json, Type typeOfT,  JsonDeserializationContext context) throws JsonParseException {
        List<String> keywords = null;
        Gson gson = new Gson();
        MetaData metaData = gson.fromJson(json, AppMetaData.class);
        JsonObject jsonObject = json.getAsJsonObject();

        if (jsonObject.has("keywords")) {
            JsonElement elem = jsonObject.get("keywords");
            if (elem != null && !elem.isJsonNull()) {

                if (jsonObject.get("keywords").isJsonArray()) {
                    keywords = gson.fromJson(jsonObject.get("keywords"),   new TypeToken<List<String>>() {
                    }.getType());
                } else {
                    String keywordString = gson.fromJson(jsonObject.get("keywords"), String.class);
                    keywords = new ArrayList<String>();
                    list.addAll(Arrays.asList(keywordString.split(",")));
                }
            }
        }
       metaData.setKeywords(keywords);
}

Then I try to apply the deserilizer:

Gson gson = new GsonBuilder()              
        .registerTypeAdapter(Data.class,new CustomDeserilizer())               
        .create();

But I get a parsing error , because is trying to deserialize Data instead of MetaData, how can I apply this deserializer to make it work right?

like image 583
Osarez Avatar asked Dec 01 '16 20:12

Osarez


People also ask

How do you deserialize with Gson?

Deserialization in the context of Gson means converting a JSON string to an equivalent Java object. In order to do the deserialization, we need a Gson object and call the function fromJson() and pass two parameters i.e. JSON string and expected java type after parsing is finished. Program output.

What is setLenient in Gson?

setLenient. public GsonBuilder setLenient() By default, Gson is strict and only accepts JSON as specified by RFC 4627. This option makes the parser liberal in what it accepts. Returns: a reference to this GsonBuilder object to fulfill the "Builder" pattern See Also: JsonReader.setLenient(boolean)

What is JsonElement in java?

public abstract class JsonElement extends java.lang.Object. A class representing an element of Json. It could either be a JsonObject , a JsonArray , a JsonPrimitive or a JsonNull .


1 Answers

I solved it creating a deserializer for my class Data.

public static class DataDeserilizer implements JsonDeserializer {
    @Override
    public Data deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {

        Gson gson = new Gson();
        Data data = gson.fromJson(json, Data.class);
        JsonObject jsonObject = json.getAsJsonObject();
        if (jsonObject.has("meta")) {
            JsonElement elem = jsonObject.get("meta");
            if (elem != null && !elem.isJsonNull()) {

                Gson gsonDeserializer = new GsonBuilder()
                        .registerTypeAdapter(MetaData.class, new CustomDeserilizer())
                        .create();
                gsonDeserializer.fromJson(jsonObject.get("meta"), Data.class);
            }
        }

        return data;
    }



}

And

Gson gson = new GsonBuilder()              
    .registerTypeAdapter(Data.class,new DataDeserilizer())               
    .create();

Pretty obvious, but is there a more elegant solution?

like image 97
Osarez Avatar answered Sep 20 '22 23:09

Osarez