fastjson2 icon indicating copy to clipboard operation
fastjson2 copied to clipboard

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

Open noear opened this issue 1 year ago • 9 comments

复现代码:

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;
        }
    }
}

noear avatar Sep 17 '24 12:09 noear

这是特性,设计如此。

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

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

CodePlayer avatar Sep 18 '24 13:09 CodePlayer

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

noear avatar Sep 18 '24 13:09 noear

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

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

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

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

CodePlayer avatar Sep 20 '24 02:09 CodePlayer

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

noear avatar Sep 22 '24 16:09 noear

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

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

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

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

CodePlayer avatar Sep 27 '24 04:09 CodePlayer

一个处理json的包请遵守json的基本规范,不要生成{a:123123L}这种非法json串.害得我们出生产事故.你们想实现特性请在规范内实现,你们使用{a:"123123L"}也行吧.

zeasly avatar Mar 27 '25 02:03 zeasly

@zeasly 同道中人哪:)

noear avatar Mar 27 '25 02:03 noear

建议是搞个开关,可进一步控制哦:)。。。至少 json 格式为符合标准很重要。

noear avatar Mar 27 '25 02:03 noear

有一个JSONWriter.Feature.NotWriteNumberClassName

   assertEquals(
                "{\"id\":1}",
                JSON.toJSONString(new Bean1(1L),
                        JSONWriter.Feature.NotWriteRootClassName,
                        JSONWriter.Feature.WriteClassName,
                        JSONWriter.Feature.NotWriteNumberClassName
                )
        );

wenshao avatar Jul 31 '25 07:07 wenshao