All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.seratch.jslack.common.json.UnknownPropertyDetectionAdapterFactory Maven / Gradle / Ivy

package com.github.seratch.jslack.common.json;

import com.google.gson.Gson;
import com.google.gson.JsonParseException;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.internal.bind.ReflectiveTypeAdapterFactory;
import com.google.gson.reflect.TypeToken;

import java.lang.reflect.Field;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * https://github.com/google/gson/issues/188#issuecomment-282746095
 */
public class UnknownPropertyDetectionAdapterFactory implements TypeAdapterFactory {

    @Override
    public  TypeAdapter create(Gson gson, TypeToken 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 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);
                StringBuilder sb = new StringBuilder();
                for (Object key : boundFields.keySet()) {
                    sb.append(key + ", ");
                }
                final String boundFieldsStr = sb.append("...").toString();

                // 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("Unknown property detected: " + key + " in " + boundFieldsStr);
                        }
                        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;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy