alibaba / fastjson2

🚄 FASTJSON2 is a Java JSON library with excellent performance.
Apache License 2.0
3.79k stars 495 forks source link

[BUG] 添加 JSONWriter.Feature.WriteClassName 特性后,long 值序列化后会有 "L" 字符。(算问题?还是有什么开关,可以关掉?) #2967

Open noear opened 2 months ago

noear commented 2 months ago

复现代码:

public class TypeTest {
    @Test
    public void test() throws Throwable {
        Bean data = new Bean();
        data.value = 12L;

        String output = JSON.toJSONString(data, JSONWriter.Feature.WriteClassName);

        System.out.println(output); //{"@type":"features.type0.TypeTest$Bean","value":12L}
        assertEquals("{\"@type\":\"features.type0.TypeTest$Bean\",\"value\":12}", output);
    }

    public static class Bean {
        private Long value;

        public Long getValue() {
            return value;
        }
    }
}
CodePlayer commented 2 months ago

这是特性,设计如此。

你设置了 WriteClassName,那么 Fastjson 就会将属性的类型信息序列化进去,这样反序列化时才会自动恢复为正确的类型。

附加一个 L 就是便于 Long 类型和 Integer 等其他整型进行区分,而且占用的额外存储空间也不大。 如果是自定义类型,则是添加一个 @type 属性,其值即为完整的类型名称,例如 package.to.ClassName

noear commented 2 months ago

@CodePlayer 希望再来个特性,能控制它的关闭:)。。。有些场景下,需要与其它框架的互通性

CodePlayer commented 1 month ago

@CodePlayer 希望再来个特性,能控制它的关闭:)。。。有些场景下,需要与其它框架的互通性

如果要与其他框架互通,那你就不应该使用 WriteClassName 这种序列化方式。 这不只是 Long 类型的 L 后缀问题,其他框架也不一定能支持 "@type" 这种自定义类型识别呀。

感觉你考虑的实现思路有些误入歧途。如果要实现不同序列化框架之间的互通:

  1. 最好都使用相同的组件,这样就没有实现上的差异
  2. 如果不能使用相同的组件,那么就使用与单一框架无关的协议来通信。如果两边对数据类型都是已知的,那在传输过程中就不必附加这种类型信息,你不需要设置 WriteClassName,直接传输 纯数据 JSON,接收方自行反序列化为已知的类型即可 。
  3. 如果数据类型对双方是不确定的,那么必须用一种两边都能识别的方式来传递数据类型信息。具体如何实现,得取决于你的实际情况。
noear commented 1 month ago

@CodePlayer 非你所想。。。大多 json 框架,都有 WriteClassName 类似的特性,都可以有 @type 属性。

CodePlayer commented 1 month ago

@CodePlayer 非你所想。。。大多 json 框架,都有 WriteClassName 类似的特性,都可以有 @type 属性。

你可以说说大多数JSON框架是哪些呢 ? 类似的特性肯定都有,但是并没有统一约定为 @type 这个Fastjson使用的的类型属性名称。

也就是 JSON框架 默认并不是互通的,本质上就是,如何保存序列化对象自身的类型信息,在 JSON 框架领域并没有一个统一的标准,不然大家都会遵循规范统一实现了。

当然,结合框架的自定义功能设置,我们还是可以将不同框架的 类型 属性名称 调整为相同的。 至于 L,你也可以设置 JSONWriter.Feature.WriteLongAsString 将 Long 值序列化为字符串。 最后,无论如何,其他 JSON框架 也要能够自定义,允许你将 L后缀 或 数值字符串 自定义反序列化为 Long 类型。