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

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 mperdik...@gmail.com on 22 Jan 2010 at 10:13

Attachments:

About this issue

  • Original URL
  • State: open
  • Created 9 years ago
  • Reactions: 10
  • Comments: 33 (1 by maintainers)

Most upvoted comments

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;
    }

}

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

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

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

The boundFields field is now in the superclass of the class returned by delegate.getClass(). So the code should work with 2.10 if you change that line to

        Field f = delegate.getClass().getSuperclass().getDeclaredField("boundFields");

We had to fix a couple of occurrences of the same problem in Google’s internal codebase. I changed the code to this slightly more robust version:

        Field f = findField(delegateAdapter.getClass(), "boundFields");
...
  private static Field findField(Class<?> startingClass, String fieldName)
      throws NoSuchFieldException {
    for (Class<?> c = startingClass; c != null; c = c.getSuperclass()) {
      try {
        return c.getDeclaredField(fieldName);
      } catch (NoSuchFieldException e) {
        // OK: continue with superclasses
      }
    }
    throw new NoSuchFieldException(fieldName + " starting from " + startingClass.getName());
  }

That should work with both pre- and post-2.10 versions.

Although Gson is in maintenance mode, this particular issue seems important enough that we should have some formal support for it instead of requiring people to use reflective hacks like this.

Imagine not resolving a critial-labeled issue in 11 years

Original issue reported on code.google.com by mperdik...@gmail.com on 22 Jan 2010 at 10:13

  • Added labels: Priority-Critical

Oh right…

Up

@eamonnmcmanus Thank you for your follow-up! I agree it would be preferable to not have to use reflection to get at these fields, and it would be great if there were a more formal mechanism.

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