美文网首页
gson的难点问题

gson的难点问题

作者: byamao1 | 来源:发表于2018-11-12 14:54 被阅读0次

Circular references

question:循环引用会引起stack overflow
solution:这个目前gson(2.8.5)都没有解决,推荐YaGson,是gson的一个fork,用法相同。

<dependency>
    <groupId>com.gilecode.yagson</groupId>
    <artifactId>yagson</artifactId>
    <version>0.4.1</version>
</dependency>

https://github.com/amogilev/yagson/blob/master/UserGuide.adoc

异常

java.lang.IllegalArgumentException: Infinity is not a valid double value as per JSON specification. To override this behavior, use GsonBuilder.serializeSpecialFloatingPointValues() method.

reason:如果你传入 Float.POSITIVE_INFINITY 值,Gson 将会抛出异常,因为这个值是不能符合 JSON 标准的。
solution:通过 GsonBuilder 设置 serializeSpecialFloatingPointValues() 。
example:

Gson gson = new GsonBuilder()
                .setPrettyPrinting()
                .serializeSpecialFloatingPointValues() // 这是关键
                .create();

https://www.jianshu.com/p/83eb1b2bc119

java.lang.IllegalArgumentException: JSON forbids NaN
and infinities: NaN

test:在这里无论是gson还是YaGson都是报错。

    @Test
    public void testInfinity2() {
        Map map = new HashMap();
        map.put(Double.NaN, "x");
        Gson gson = new YaGsonBuilder()
                .setPrettyPrinting()
//                .enableComplexMapKeySerialization()
                .serializeSpecialFloatingPointValues()
                .create();
        String json = gson.toJson(map);
        log.info(json);

        Map map2 = gson.fromJson(json, HashMap.class);

    }

https://github.com/ar-android/google-gson/issues/639

reason:虽然GsonBuilder可以通过setLenient将JsonWriter.lenient = true:

        Gson gson = new GsonBuilder()
                .setPrettyPrinting()
                .setLenient()   // here
                .serializeSpecialFloatingPointValues()
                .create();

但是JsonTreeWriter.lenient仍然是false。(JsonTreeWriter继承自JsonWriter),通过查看源码得知原因:

TypeAdapter类:
  public final JsonElement toJsonTree(T value, WriteContext ctx) {
    try {
       // new的JsonTreeWriter.lenient为false,此后再无更改
      JsonTreeWriter jsonWriter = new JsonTreeWriter();  
      write(jsonWriter, value, ctx);
      return jsonWriter.get();
    } catch (IOException e) {
      throw new JsonIOException(e);
    }
  }

这就没办法了,只能改源码(未经过全面检测,后果自负):

JsonTreeWriter类:
  public JsonTreeWriter() {
    super(UNWRITABLE_WRITER);
    this.setLenient(true);  //  here,简单粗暴
  }

类型接管

注意:

ImmutableList序列化的类型实际是RegularImmutableList不能使用父类ImmutableList来替上面的子类型RegularImmutableList可以使用registerTypeHierarchyAdapter,方法同registerTypeAdapter
https://www.jianshu.com/p/3108f1e44155

对于又有Circular references又有ImmutableList类型的成员反序列化,只能改YaGson源码。

以下是正常反序列化
com.google.gson.internal.bind
CollectionTypeAdapterFactory.readOptionallyAdvisedInstance line257
MapTypeAdapterFactory.readOptionallyAdvisedInstance line239

以下是引用变量的反序列化
com.google.gson.internal.bind
ReflectiveTypeAdapterFactory$DefaultBoundField

// 加入了对各种guava不变类的判断
    protected void applyReadFieldValue(Object value, Object fieldValue) throws IllegalAccessException {
      if (fieldValue != null || !isPrimitive) {
        Class clazz = field.getType();
        if (clazz.equals(ImmutableList.class)) {
          field.set(value, ImmutableList.copyOf((Collection<?>) fieldValue));
        } else if (clazz.equals(ImmutableSet.class)) {
          field.set(value, ImmutableSet.copyOf((Collection<?>) fieldValue));
        } else if (clazz.equals(ImmutableMap.class)) {
          field.set(value, ImmutableMap.copyOf((Map<?, ?>) fieldValue));
        } else {
          field.set(value, fieldValue);
        }
      }
    }

相关文章

  • gson的难点问题

    Circular references question:循环引用会引起stack overflowsolutio...

  • JSONArray的解析

    问题1:类似String s = "[ { },{ },{ } ]";这种结构的解析 方法一: Gson gson...

  • Gson问题

    时间类型的问题 当我们为传输协议写Bean的时候,时间属性通常情况下都是时间戳的形式,然而当我们将其定义为Date...

  • Gson格式化报错com.google.gson.JsonSyn

    日期 2018-05-07 问题 Gson格式化报错 com.google.gson.JsonSyntaxExce...

  • gson解析对象闪退

    问题描述: 在使用谷歌的gson把对象转成json时老是卡住,闪退。 String json =new Gson(...

  • 2018-01-11

    Gson解析复杂json数据常用的两种解析方式 Gson gson = new Gson(); 1.gson.fr...

  • Gson教程 Apache POI教程 Guava教程Apac

    Gson教程 Gson概述Gson环境设置Gson第一个应用Gson classGson对象序列化Gson数据绑定...

  • list集合转换为json

    //后台Gson gson=new Gson();String json=gson.toJson(集合, new ...

  • Gson注解应用 介绍

    在学习项目Ribble-master时需要的Gson问题总结。众所周知Gson是谷歌设计的用于json字符串解析和...

  • GSON 解析 JSON

    GSON JSON 介绍 Gson 下载 Gson 解析 和 格式化Gson 格式化Gson 解析 解析asset...

网友评论

      本文标题:gson的难点问题

      本文链接:https://www.haomeiwen.com/subject/koccfqtx.html