3

While converting Java object to Json string using GSON API, I also want to fail this Json conversion if any of the annotated attribute is null.

For example

public class Order{

@SerializedName("orderId")
@Expose
@Required
private Integer id;

//getter & setter available for id
}

Now as I am doing

Order order = new Order();

JSONObject jsonobj = new JSONObject(gson.toJson(order));

I want to fail the above Java to Json transformation if any of the @Required attribute is null Is this possible using GSON?

1

1 Answer 1

7

I wanted to fail Java to Json conversion, if any of the Java attribute is null which is annotated as @Required, I am able to achieve this using following approach. Please let me know if you see any issues:

class RequiredKeyAdapterFactory implements TypeAdapterFactory {

    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {

        final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);

        return new TypeAdapter<T>() {
            @Override
            public void write(JsonWriter out, T value) throws IOException {
                if (value != null) {

                    Field[] fields = value.getClass().getDeclaredFields();

                    for (int i = 0; i < fields.length; i++) {
                        if (fields[i]
                                .isAnnotationPresent(Required.class)) {
                            validateNullValue(value, fields[i]);
                        }

                    }
                }
                delegate.write(out, value);
            }

            private <T> void validateNullValue(T value, Field field) {
                field.setAccessible(true);
                Class t = field.getType();
                Object v = null;
                try {
                    v = field.get(value);
                } catch (IllegalArgumentException | IllegalAccessException e) {
                    throw new IllegalArgumentException(e);
                }
                if (t == boolean.class && Boolean.FALSE.equals(v)) {
                    throw new IllegalArgumentException(field + " is null");
                } else if (t.isPrimitive()
                        && ((Number) v).doubleValue() == 0) {

                    throw new IllegalArgumentException(field + " is null");
                } else if (!t.isPrimitive() && v == null) {
                    throw new IllegalArgumentException(field + " is null");

                }
            }

            @Override
            public T read(JsonReader in) throws IOException {
                return delegate.read(in);
            }

        };
    }
}

RequiredKeyAdapterFactory requiredKeyAdapterFactory = new RequiredKeyAdapterFactory();
Gson gson = new GsonBuilder().registerTypeAdapterFactory(requiredKeyAdapterFactory)
        .create();

This is working

Sign up to request clarification or add additional context in comments.

3 Comments

hi @Preetam: can you please provide us with definition of Required interface
It should be like simple annotation which can be used for all attribute which are mandatory. @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Required { //nothing }
Note that this will fail if the deserialized JSON contains a primitive number set to 0 (because of the if (t.isPrimitive() && ((Number) v).doubleValue() == 0) line) but I don't think there's any good way around that unless you make every serialized value an object.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.