ALLOW_UNQUOTED_FIELD_NAMES在杰肯JSON库中

2022-09-02 13:41:16

我正在使用 jackson 库对 JSON 进行序列化/反序列化。我需要此JSON具有尽可能小的大小,因此我启用了ALLOW_UNQUOTED_FIELD_NAMES功能以消除所有引号。我知道删除引号不是标准的json,但是使json变小是该项目的硬性要求。生成的json工作正常,但是当我尝试读取json值时,我得到一个异常:

org.codehaus.jackson.JsonParseException:意外字符('9'(代码 57)):期望有效的名称字符(用于未加引号的名称)或双引号(对于引号)在 [来源:java.io.StringReader@1347d75;行:1,列:3] 开始字段名称

当我阅读此json时,上面的异常被抛出:

{90110a2e-febd-470f-afa4-cf7e890d31b9:0,eec652ad-a4d9-4eb1-8d24-7c1a0c29449f:1}

我读它的方式是:

Map<String, Object> valuesMap = oM.readValue(json, new TypeReference<Map<String, Object>>() {});

我用于读取和写入值的对象映射器是:

private static final ObjectMapper om = new ObjectMapper();
static {
    om.configure(JsonGenerator.Feature.QUOTE_FIELD_NAMES, false);
    om.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
    om.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, true);
    om.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    om.getSerializationConfig().setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
}

我在发送方和接收方项目中都使用 Jackson 的 1.6.3 版。此功能所需的版本是1.2 +,所以我想也许我没有使用这个版本,但我的接收器是Spring应用程序,我已经检查了libs文件夹中安装的库是1.6.3。

我可能做错了什么?也许此功能不能与地图一起使用。

我还有另一个问题,到目前为止,我只是发送一个地图,其中键只是一个uuid值,值是一个数字。如果我发送带有特殊字符且启用了ALLOW_UNQUOTED_FIELD_NAMES功能的值,我是否有任何问题?杰克逊会逃脱这个角色吗?

谢谢。


答案 1

好吧,我认为Pingw33n的答案几乎是正确的。所以:是的,你可以使用这个功能;但它是相当启发式的 - 因为没有关于非引号名称应该如何工作的规范(毕竟,JSON允许任何和所有字符的名称!或者,如果要使用任何逃生机制,任何人都会猜测应该写什么或接受什么。

在这种特殊情况下,可能是“-”字符导致问题。它不是Javascript名称的合法部分,Javascript名称是Jackson使用的近似值。

一种可能的解决方案是让杰克逊在属性名称中转义这些字符(我不记得目前是如何完成的;如果引用任何名称字符)。如果你能找出一个简单的测试用例,你可以在Jackson Jira上提交一个Jira请求,以添加转义(并确保解析器可以取消通常的反斜杠版本)。


答案 2

似乎杰克逊在某些情况下会产生这样的输出,即使打开也无法读取自己。您可能需要为非标准输入解析实现自定义。QUOTE_FIELD_NAMESALLOW_UNQUOTED_FIELD_NAMESJsonParser

问题是您正在生成非标准JSON,并且无法保证客户端会正确处理它。但是,如果您不将其公开到应用程序之外,并且非常关心大小,则可以解析/生成二进制格式,例如Jackson's Smile。见 http://www.cowtowncoder.com/blog/archives/2010/09/entry_418.html(2.4)。