Gson: Support handlers for unknown properties, useful for error handling

Created on 19 Mar 2015  路  25Comments  路  Source: google/gson

What steps will reproduce the problem?
1. create a JSON string containing extra attributes
2. invoke Gson.fromJson supplying a class with fewer elements
3. GSON successfully instantiates the class without protesting about the 
existence of extra attributes in the string.

What is the expected output? What do you see instead?
1. define class A containing two fields: name and surname
2. define class B containing only one field: name
3. transform an instance of class A to Json string and use the Json string 
to create an instance of class B.

GSON doesn't complain. Even if this is the intended behavior, shouldn't 
there be an option to enforce stricter parsing?

What version of the product are you using? On what operating system?
gson-1.4

Please provide any additional information below.


Original issue reported on code.google.com by [email protected] on 22 Jan 2010 at 10:13

Attachments:

Priority-Critical Type-Enhancement auto-migrated

Most helpful comment

I manage to workaround this issue using a class similar to the following:

public class ValidatorAdapterFactory implements TypeAdapterFactory {

    @Override
    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
        // If the type adapter is a reflective type adapter, we want to modify the implementation using reflection. The
        // trick is to replace the Map object used to lookup the property name. Instead of returning null if the
        // property is not found, we throw a Json exception to terminate the deserialization.
        TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);

        // Check if the type adapter is a reflective, cause this solution only work for reflection.
        if (delegate instanceof ReflectiveTypeAdapterFactory.Adapter) {

            try {
                // Get reference to the existing boundFields.
                Field f = delegate.getClass().getDeclaredField("boundFields");
                f.setAccessible(true);
                Map boundFields = (Map) f.get(delegate);

                // Then replace it with our implementation throwing exception if the value is null.
                boundFields = new LinkedHashMap(boundFields) {

                    @Override
                    public Object get(Object key) {

                        Object value = super.get(key);
                        if (value == null) {
                            throw new JsonParseException("invalid property name: " + key);
                        }
                        return value;

                    }

                };
                // Finally, push our custom map back using reflection.
                f.set(delegate, boundFields);

            } catch (Exception e) {
                // Should never happen if the implementation doesn't change.
                throw new IllegalStateException(e);
            }

        }
        return delegate;
    }

}

All 25 comments

I think a reasonable fix for this would be to permit the user to register a 
handler to be notified whenever an unknown property is encountered. Perhaps 
this:
  interface UnknownFieldHandler {
    void handle(JsonObject object, String name, JsonElement value);
  }

Then we could build in a few implementations: one that ignores unknown fields, 
one that logs unknown fields, and one that throws on unknown fields. Users 
could configure their GSON to be as strict or forgiving as necessary.

Original comment by limpbizkit on 3 Nov 2010 at 4:53

  • Changed title: Support handlers for unknown properties, useful for error handling
  • Added labels: Type-Enhancement, Milestone-Release1.7
  • Removed labels: Type-Defect
Issue 262 has been merged into this issue.

Original comment by limpbizkit on 30 Dec 2011 at 6:38

It is good to get object instance, but also is useful information about 
character position.

Original comment by [email protected] on 30 Dec 2011 at 7:33

Original comment by limpbizkit on 12 Feb 2012 at 8:44

  • Removed labels: Milestone-Release1.7

Original comment by [email protected] on 3 Dec 2012 at 6:18

A handler might not be very Gsonic, but some way to let the Gson client know 
that extraneous metadata existed in the subject JSON would be useful.

Original comment by [email protected] on 7 Jan 2013 at 9:05

we have been hacked and have not agreed to your terms

Original comment by [email protected] on 13 Jan 2013 at 2:17

please help get these people out of our stuff. fbi has been notified and law 
enforcement report filed. sincerely,
                           the real timpyates

Original comment by [email protected] on 13 Jan 2013 at 2:19

Original comment by limpbizkit on 4 Feb 2013 at 4:00

  • Added labels: Priority-Critical
  • Removed labels: Priority-Medium
Issue 495 has been merged into this issue.

Original comment by limpbizkit on 4 Feb 2013 at 4:01

Any new about this enhancement ? or a workaround ?

Original comment by [email protected] on 11 Mar 2014 at 9:41

I submitted pull request https://github.com/google/gson/pull/660 for this

Any updates on this issue? looking forward for the fix...

Is there a workaround for this issue which we can do until a fix is provided?

I manage to workaround this issue using a class similar to the following:

public class ValidatorAdapterFactory implements TypeAdapterFactory {

    @Override
    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
        // If the type adapter is a reflective type adapter, we want to modify the implementation using reflection. The
        // trick is to replace the Map object used to lookup the property name. Instead of returning null if the
        // property is not found, we throw a Json exception to terminate the deserialization.
        TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);

        // Check if the type adapter is a reflective, cause this solution only work for reflection.
        if (delegate instanceof ReflectiveTypeAdapterFactory.Adapter) {

            try {
                // Get reference to the existing boundFields.
                Field f = delegate.getClass().getDeclaredField("boundFields");
                f.setAccessible(true);
                Map boundFields = (Map) f.get(delegate);

                // Then replace it with our implementation throwing exception if the value is null.
                boundFields = new LinkedHashMap(boundFields) {

                    @Override
                    public Object get(Object key) {

                        Object value = super.get(key);
                        if (value == null) {
                            throw new JsonParseException("invalid property name: " + key);
                        }
                        return value;

                    }

                };
                // Finally, push our custom map back using reflection.
                f.set(delegate, boundFields);

            } catch (Exception e) {
                // Should never happen if the implementation doesn't change.
                throw new IllegalStateException(e);
            }

        }
        return delegate;
    }

}

Thanks @ikus060. I was able to adapt your approach so I can log error messages on unrecognized properties, rather than silently ignoring them as is done by default.

The solution is a bit ugly, but it work...

Do we have this fix as part of the GSON library now ?

Nice work-around but I will have to adapt it to be compatible with my IdExclusionStrategy that tells gson to ignore the id field. Gson now throws errors wherever it sees the id in JSON.

My intention is to ignore ids on serialization, and by design it would be compatible because the TypeAdaptor for this example is only implemented for gets / deserialization. However ExclusionStrategies are deserialization/serialization-agnostic - work on both.

EDIT: ok, I have adapted the work-around for us with ExclusionStrategies by building two Gson objects, one for serializing, one for deserializing.

Any updates on this issue? It was bumped to "Critical" priority three years ago.

Up

Up

wow, this is astounding... definitely moving away from gson. why is this basic feature not present?

I'm looking for an alternative to gson, this problem should have been fixed in the last 10 years

Still not fixed????
This seems to be a pattern with google tools, develop something 80% to 90% and then walk away from it :(

Was this page helpful?
0 / 5 - 0 ratings

Related issues

GoogleCodeExporter picture GoogleCodeExporter  路  14Comments

inder123 picture inder123  路  17Comments

JakeWharton picture JakeWharton  路  39Comments

kdehairy picture kdehairy  路  43Comments

GoogleCodeExporter picture GoogleCodeExporter  路  15Comments