使用null作为映射键时反序列化失败

时间:2019-04-03 07:46:56

标签: java

使用null作为地图键时,Gson反序列化失败

 Gson gson = new GsonBuilder()
                    .serializeNulls()
                    .serializeSpecialFloatingPointValues()
                    .create();
            Map<Integer, String> mapData = new HashMap<Integer, String>();
            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); 

例外:

Exception in thread "main" com.google.gson.JsonSyntaxException: java.lang.NumberFormatException: For input string: "null"

以下代码段效果很好。

Gson gson = new GsonBuilder()
                .serializeNulls()
                .serializeSpecialFloatingPointValues()
                .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); 

输出:

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

1 个答案:

答案 0 :(得分:1)

您可以为Integer创建TypeAdapter

Gson gson = new GsonBuilder()
        .serializeNulls()
        .serializeSpecialFloatingPointValues()
        .registerTypeAdapter(Integer.class, new TypeAdapter<Integer>() {
            @Override
            public void write(JsonWriter jsonWriter, Integer integer) throws IOException {
                jsonWriter.jsonValue(String.valueOf(integer));
            }
            @Override
            public Integer read(JsonReader jsonReader) throws IOException {
                if (jsonReader.peek() == JsonToken.NULL) {
                    jsonReader.nextNull();
                    return null;
                } else {
                    String numberStr = jsonReader.nextString();
                    return "null".equals(numberStr) ? null : Integer.valueOf(numberStr);
                }
            }
        })
        .create();

输出:

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

在没有自定义Integer适配器的情况下,null会为值工作而对密钥不起作用的原因是映射适配器序列化每个密钥的方式:密钥始终是JSON中的String,它既不是int也不是null 。您可以在输出中看到它:{"null":"abc"}{"abc":null}

查看map type adapter的实现。