julman99 / gson-fire

A java library that adds some very useful features to Gson, like Date serializing to unix timestamp or RFC3339, method (getters) serialization, pre/post processors and many others. Check out the documentation to learn how to use it!
http://gsonfire.io
Other
229 stars 37 forks source link

Can't serialize NaN #39

Closed daw3rd closed 6 years ago

daw3rd commented 6 years ago

Per the subject, if I get the GsonBuilder and set it to allow NaN, it is not taking effect and I get the following:

Exception in thread "main" java.lang.IllegalArgumentException: JSON forbids NaN and infinities: NaN see comments below for updated exception and code.

julman99 commented 6 years ago

Thanks for reporting this. I will check during the weekend and release a new version if I am able to fix it

daw3rd commented 6 years ago

Hmm, the code above is not quite correct. I'm trying to reproduce with a simple example, but the above is using my other code (i.e. PolyGson class). I'll try and narrow this down.

julman99 commented 6 years ago

Ok, please make sure you use the latest gson-fire version since I fixed some issues a while ago regarding lenient parsing

daw3rd commented 6 years ago

Yes, I'm using 1.8.2 from the maven repo. Here's is the updated code that seems to require setting preprocessors AND a type selector

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;

import io.gsonfire.GsonFireBuilder;
import io.gsonfire.PostProcessor;
import io.gsonfire.TypeSelector;

public class GsonFireBug {

    private static class GSONAdapter implements PostProcessor<Object>, TypeSelector<Object> {

        private static final String CLASSNAME = "$type";

        @Override
        public void postDeserialize(Object result, JsonElement src, Gson gson) { }

        /**
         * After serializing, we add the name of the class to the JsonElement if it represent a class.
         */
        @Override
        public void postSerialize(JsonElement result, Object src, Gson gson) {
//          if (result.isJsonObject())
//              result.getAsJsonObject().addProperty(CLASSNAME, src.getClass().getName());
        }

        /**
         * If the element is a JsonObject, then expect the {@link #CLASSNAME} field to specify the name of the class to use.
         */
        @Override
        public Class<? extends Object> getClassForElement(JsonElement readElement) {
//          if (readElement.isJsonObject()) {
//              String className = readElement.getAsJsonObject().get(CLASSNAME).toString();
//              className = className.replaceAll("\"", "");
//              try {
//                  return Class.forName(className);
//              } catch (ClassNotFoundException e) {
//                  throw new IllegalArgumentException("Could not load class " + className, e);
//              }
//          }
            return null;    // Else use the default.
        }

    }

    public static Gson getGson(boolean triggerBug) {
        GsonFireBuilder builder = new GsonFireBuilder();
        GSONAdapter adapter = new GSONAdapter();
        if (triggerBug) {
            builder.registerPostProcessor(Object.class, adapter);
            builder.registerTypeSelector(Object.class, adapter);
        }
        GsonBuilder gb = builder.createGsonBuilder();
        gb.serializeSpecialFloatingPointValues();
        Gson gson = gb.create();
        return gson;
    }

    public static class Buggy {
        double a = Double.NaN;
    }

    public static void main(String[] args) {
        String json;
        Buggy fm = new Buggy(); 

        json = getGson(false).toJson(fm);   // Succeeds
        System.out.println(json);

        json = getGson(true).toJson(fm);    // Fails 
        System.out.println(json);
    }   
}
daw3rd commented 6 years ago

And my apologies, but here is an updated output and stack trace from the previous post

{"a":NaN}
Exception in thread "main" java.lang.IllegalArgumentException: JSON forbids NaN and infinities: NaN
    at com.google.gson.internal.bind.JsonTreeWriter.value(JsonTreeWriter.java:191)
    at com.google.gson.internal.bind.TypeAdapters$13.write(TypeAdapters.java:358)
    at com.google.gson.internal.bind.TypeAdapters$13.write(TypeAdapters.java:347)
    at com.google.gson.TypeAdapter.toJsonTree(TypeAdapter.java:234)
    at io.gsonfire.gson.TypeSelectorTypeAdapterFactory$TypeSelectorTypeAdapter.write(TypeSelectorTypeAdapterFactory.java:58)
    at io.gsonfire.gson.NullableTypeAdapter.write(NullableTypeAdapter.java:26)
    at com.google.gson.TypeAdapter.toJsonTree(TypeAdapter.java:234)
    at io.gsonfire.gson.HooksTypeAdapter.write(HooksTypeAdapter.java:40)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:125)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:243)
    at com.google.gson.TypeAdapter.toJsonTree(TypeAdapter.java:234)
    at io.gsonfire.gson.TypeSelectorTypeAdapterFactory$TypeSelectorTypeAdapter.write(TypeSelectorTypeAdapterFactory.java:58)
    at io.gsonfire.gson.NullableTypeAdapter.write(NullableTypeAdapter.java:26)
    at com.google.gson.TypeAdapter.toJsonTree(TypeAdapter.java:234)
    at io.gsonfire.gson.HooksTypeAdapter.write(HooksTypeAdapter.java:40)
    at com.google.gson.Gson.toJson(Gson.java:669)
    at com.google.gson.Gson.toJson(Gson.java:648)
    at com.google.gson.Gson.toJson(Gson.java:603)
    at com.google.gson.Gson.toJson(Gson.java:583)
    at GsonFireBug.main(GsonFireBug.java:72)
julman99 commented 6 years ago

@daw3rd I was able to find a fix for this, I will publish a beta version tonight since I was not able to fully test over the weekend

julman99 commented 6 years ago

@daw3rd can you try version 1.9.0-alpha1 and let me know if it fixes your issue?

Thanks

daw3rd commented 6 years ago

Seems to have done the trick. Thanks.

julman99 commented 6 years ago

Great, I will do more unit testing to ensure there are no regressions because of this change, and then release 1.9.0

Will update here once I do

Thanks for reporting!

julman99 commented 6 years ago

FYI just released version 1.8.3 that contains this fix.

It is basically the same alpha you are running, I decided to make it a minor release since it only contains that fix

daw3rd commented 6 years ago

Great. Thanks. I've rebuilt with 1.8.3 and all is well. Thanks for the quick fix.