GSON ignore elements with wrong type

后端 未结 5 981
陌清茗
陌清茗 2020-12-08 11:22

I\'m using Retrofit (in combination with OkHttp and GSON) to communicate with an online webservice. The webservice has a default wrapper around all it\'s responses, similar

相关标签:
5条回答
  • 2020-12-08 11:43

    I've had a similar problem and came up with the following solution in the end:

    In stead of trying to parse your element into a String or Array, try storing the data to a simple java.lang.Object

    This prevents the parsing from crashing or throwing an exception.

    eg. with GSON annotations the property of your model would look like this:

    @SerializedName("resultObj")
    @Expose
    private java.lang.Object resultObj;
    

    Next, when accessing your data at runtime, you can check if your resultObj property is an instance of String or not.

    if(apiResultObject instanceof String ){
        //Cast to string and do stuff
    
    } else{
        //Cast to array and do stuff
    
    }
    

    Original post: https://stackoverflow.com/a/34178082/3708094

    0 讨论(0)
  • 2020-12-08 12:00

    First, this is a bad API design that you're dealing with. :-(

    You can use a custom JsonDeserializer to handle this case.

    Register it with Retrofit:

    MyJsonDeserializer deserializer = new MyJsonDeserializer()).create();
    final Gson gson = new GsonBuilder().registerTypeAdapter(ApiResult.class, deserializer);
    RestAdapter restAdapter = new RestAdapter.Builder()
        .setEndpoint(API_URL)
        .setConverter(new GsonConverter(gson))
        .build();
    
    0 讨论(0)
  • 2020-12-08 12:00

    You can use this code as well:

    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    yourObject = objectMapper.readValue(jsonString, <ClassName>.class);
    
    0 讨论(0)
  • 2020-12-08 12:02

    Define your model like this:

    public class ApiResult {
    
        private String error;
        private String message;
        private String resultCode;
        private MyResultObject resultObj;
    }
    

    Then, create a TypeAdapterFactory for MyResultObject:

    public class MyResultObjectAdapterFactory implements TypeAdapterFactory {
    
        @Override
        @SuppressWarnings("unchecked")
        public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
            if (type.getRawType()!= MyResultObject.class) return null;
    
            TypeAdapter<MyResultObject> defaultAdapter = (TypeAdapter<MyResultObject>) gson.getDelegateAdapter(this, type);
            return (TypeAdapter<T>) new MyResultObjectAdapter(defaultAdapter);
        }
    
        public class MyResultObjectAdapter extends TypeAdapter<MyResultObject> {
    
            protected TypeAdapter<MyResultObject> defaultAdapter;
    
    
            public MyResultObjectAdapter(TypeAdapter<MyResultObject> defaultAdapter) {
                this.defaultAdapter = defaultAdapter;
            }
    
            @Override
            public void write(JsonWriter out, MyResultObject value) throws IOException {
                defaultAdapter.write(out, value);
            }
    
            @Override
            public MyResultObject read(JsonReader in) throws IOException {
                /* 
                This is the critical part. So if the value is a string,
                Skip it (no exception) and return null.
                */
                if (in.peek() == JsonToken.STRING) {
                    in.skipValue();
                    return null;
                }
                return defaultAdapter.read(in);
            }
        }
    }
    

    Finally, register MyResultObjectAdapterFactory for Gson:

    Gson gson = new GsonBuilder()
        .registerTypeAdapterFactory(new MyResultObjectAdapterFactory())
        .create();
    

    Now, when deserializing an ApiResult json with that Gson object, resultObj will be set null if it is a string.

    I Hope this solves your problem =)

    0 讨论(0)
  • 2020-12-08 12:09

    I'm reusing my reponse pojo.

    In one response it's String and another response it's List<MajicalModel> magicalField so one parsing failed.

    I change it to com.google.gson.JsonElement magicalField; it's work for me. This way it parse raw json and also ignore type mismatch.

    0 讨论(0)
提交回复
热议问题