question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Deserisation fails with when using null numeric primitives as map keys

See original GitHub issue

What did you do:

Ran:

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

import java.util.HashMap;
import java.util.Map;

public class Test {
    static class MyType {
        public Map<Integer, Integer> map = new HashMap<>();
    }

    public static void main(String[] args) {
        MyType instance = new MyType();
        instance.map.put(null, 1);

        Gson serialiser = new GsonBuilder()
                .enableComplexMapKeySerialization()
                .serializeNulls()
                .setPrettyPrinting()
                .create();

        String data = serialiser.toJson(instance);
        System.out.println(data);

        try {
            MyType newInstance = serialiser.fromJson(data, MyType.class);
            System.out.println("Success");
        } catch (Exception e) {
            e.printStackTrace(System.out);
        }
    }
}

What happened

Deserialisation fails:

{
  "map": {
    "null": 1
  }
}
com.google.gson.JsonSyntaxException: java.lang.NumberFormatException: For input string: "null"
	at com.google.gson.internal.bind.TypeAdapters$7.read(TypeAdapters.java:228)
	at com.google.gson.internal.bind.TypeAdapters$7.read(TypeAdapters.java:218)
	at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:41)
	at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:186)
	at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:145)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:131)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:222)
	at com.google.gson.Gson.fromJson(Gson.java:927)
	at com.google.gson.Gson.fromJson(Gson.java:892)
	at com.google.gson.Gson.fromJson(Gson.java:841)
	at com.google.gson.Gson.fromJson(Gson.java:813)
	at Test.main(Test.java:27)
Caused by: java.lang.NumberFormatException: For input string: "null"
	at java.base/jdk.internal.math.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2054)
	at java.base/jdk.internal.math.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
	at java.base/java.lang.Double.parseDouble(Double.java:543)
	at com.google.gson.stream.JsonReader.nextInt(JsonReader.java:1201)
	at com.google.gson.internal.bind.TypeAdapters$7.read(TypeAdapters.java:226)
	... 11 more

What did you expect to happen:

Either both serialisation and deserilisation to either succeed or fail (making the handling consistent between the two modes).

It seems that only one mode does not handle this case. I know that null is an invalid json map key, but perhaps the library should handle a special “null” key when the type is a nullable primitive.

It seems that this is also broken for strings, as you can serialise a null, and get "null" back after deserilisation.

Note

Strangely it works okay if you serialise a simple map (not embedded in an object).

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:5

github_iconTop GitHub Comments

1reaction
AudriusButkeviciuscommented, Sep 15, 2018

What exactly would you be breaking? Preventing null key serialisation? What about deserialising “null” strings into nulls for boxed primitives (other than string I guess)

0reactions
yanxinyuancommented, Apr 3, 2019

I also think it is an issue, here is the code:

Scenario 1:

Gson gson = new GsonBuilder().serializeNulls().create();
Map<String, Integer> mapData = new HashMap<>();
mapData.put("abc", null);
String data = gson.toJson(mapData);
System.out.println(data);
Type type = TypeToken.getParameterized(HashMap.class, String.class, Integer.class).getType();
Object obj = gson.fromJson(data, type);
System.out.println(obj);

The code runs well and got the result

{"abc":null}
{abc=null}

Scenario 2:

Gson gson = new GsonBuilder().serializeNulls().create();
Map<Integer, String> mapData = new HashMap<>();
mapData.put(null, "abc");
String data = gson.toJson(mapData);
System.out.println(data);
Type type = TypeToken.getParameterized(HashMap.class, Integer.class, String.class).getType();
Object obj = gson.fromJson(data, type);
System.out.println(obj);

The code runs failed, and get an exception:

Exception in thread "main" com.google.gson.JsonSyntaxException: java.lang.NumberFormatException: For input string: "null"
	at com.google.gson.internal.bind.TypeAdapters$7.read(TypeAdapters.java:227)
	at com.google.gson.internal.bind.TypeAdapters$7.read(TypeAdapters.java:217)
	at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:41)
	at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:186)
	at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:145)
	at com.google.gson.Gson.fromJson(Gson.java:888)
	at com.google.gson.Gson.fromJson(Gson.java:853)
	at com.google.gson.Gson.fromJson(Gson.java:802)
	at com.delta.cornerstone.common.serialization.gson.user.UserSerializationByGson.main(UserSerializationByGson.java:41)
Caused by: java.lang.NumberFormatException: For input string: "null"
	at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2043)
	at sun.misc.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
	at java.lang.Double.parseDouble(Double.java:538)
	at com.google.gson.stream.JsonReader.nextInt(JsonReader.java:1201)
	at com.google.gson.internal.bind.TypeAdapters$7.read(TypeAdapters.java:225)
	... 8 more

So it seems Gson can only handle the “NULL” when it is the value of the map.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Deserialization fails with when using null as map key
You can create TypeAdapter for Integer : Gson gson = new GsonBuilder() .serializeNulls() .serializeSpecialFloatingPointValues() .
Read more >
DeserializationFeature (jackson-databind 2.6.0 API) - FasterXML
Feature that determines whether encountering of JSON null is an error when deserializing into Java primitive types (like 'int' or 'double').
Read more >
Jackson - Working with Maps and nulls - Baeldung
How to serialize Maps with a null key or null values using Jackson.
Read more >
DeserializationFeature (jackson-databind 2.4.5 API) - javadoc.io
Feature that determines whether encountering of JSON null is an error when deserializing into Java primitive types (like 'int' or 'double').
Read more >
Java Map - Jenkov.com
to a Map as key or value, the primitive values will be auto-boxed before being ... Here is an example of using a...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found