[BUG] 添加 JSONWriter.Feature.WriteClassName 特性后,long 值序列化后会有 "L" 字符。(算问题?还是有什么开关,可以关掉?)
复现代码:
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;
}
}
}
这是特性,设计如此。
你设置了 WriteClassName,那么 Fastjson 就会将属性的类型信息序列化进去,这样反序列化时才会自动恢复为正确的类型。
附加一个 L 就是便于 Long 类型和 Integer 等其他整型进行区分,而且占用的额外存储空间也不大。
如果是自定义类型,则是添加一个 @type 属性,其值即为完整的类型名称,例如 package.to.ClassName。
@CodePlayer 希望再来个特性,能控制它的关闭:)。。。有些场景下,需要与其它框架的互通性
@CodePlayer 希望再来个特性,能控制它的关闭:)。。。有些场景下,需要与其它框架的互通性
如果要与其他框架互通,那你就不应该使用 WriteClassName 这种序列化方式。
这不只是 Long 类型的 L 后缀问题,其他框架也不一定能支持 "@type" 这种自定义类型识别呀。
感觉你考虑的实现思路有些误入歧途。如果要实现不同序列化框架之间的互通:
- 最好都使用相同的组件,这样就没有实现上的差异
- 如果不能使用相同的组件,那么就使用与单一框架无关的协议来通信。如果两边对数据类型都是已知的,那在传输过程中就不必附加这种类型信息,你不需要设置
WriteClassName,直接传输 纯数据 JSON,接收方自行反序列化为已知的类型即可 。 - 如果数据类型对双方是不确定的,那么必须用一种两边都能识别的方式来传递数据类型信息。具体如何实现,得取决于你的实际情况。
@CodePlayer 非你所想。。。大多 json 框架,都有 WriteClassName 类似的特性,都可以有 @type 属性。
@CodePlayer 非你所想。。。大多 json 框架,都有 WriteClassName 类似的特性,都可以有
@type属性。
你可以说说大多数JSON框架是哪些呢 ?
类似的特性肯定都有,但是并没有统一约定为 @type 这个Fastjson使用的的类型属性名称。
也就是 JSON框架 默认并不是互通的,本质上就是,如何保存序列化对象自身的类型信息,在 JSON 框架领域并没有一个统一的标准,不然大家都会遵循规范统一实现了。
当然,结合框架的自定义功能设置,我们还是可以将不同框架的 类型 属性名称 调整为相同的。
至于 L,你也可以设置 JSONWriter.Feature.WriteLongAsString 将 Long 值序列化为字符串。
最后,无论如何,其他 JSON框架 也要能够自定义,允许你将 L后缀 或 数值字符串 自定义反序列化为 Long 类型。
一个处理json的包请遵守json的基本规范,不要生成{a:123123L}这种非法json串.害得我们出生产事故.你们想实现特性请在规范内实现,你们使用{a:"123123L"}也行吧.
@zeasly 同道中人哪:)
建议是搞个开关,可进一步控制哦:)。。。至少 json 格式为符合标准很重要。
有一个JSONWriter.Feature.NotWriteNumberClassName
assertEquals(
"{\"id\":1}",
JSON.toJSONString(new Bean1(1L),
JSONWriter.Feature.NotWriteRootClassName,
JSONWriter.Feature.WriteClassName,
JSONWriter.Feature.NotWriteNumberClassName
)
);