17

我正在使用杰克逊库对 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 功能的特殊字符的值,我会遇到什么问题吗?杰克逊会逃脱这个角色吗?

谢谢。

4

5 回答 5

6

好的,我认为 Pingw33n 的回答非常正确。所以:是的,您可以使用该功能;但它是相当启发式的——因为没有关于不带引号的名称应该如何工作的规范(毕竟,JSON 允许名称中的任何和所有字符!);或者,如果要使用任何转义机制,那么任何人都可以猜测应该编写或接受什么。

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

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

于 2011-01-27T19:03:46.043 回答
5

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

问题是您正在生成非标准 JSON,并且不能保证客户端会正确处理它。但是,如果您不将它暴露在您的应用程序之外并且非常关心大小,您可以解析/生成像 Jackson's Smile这样的二进制格式。请参阅http://www.cowtowncoder.com/blog/archives/2010/09/entry_418.html (2.4)。

于 2011-01-27T12:38:00.733 回答
3

我相信这个问题与Javascript sintax有关,而不是与杰克逊或JSON有关。

在 Javascript 中,名称是一个字母,可选地后跟一个或多个字母、数字或下划线,因此 90110a2e-febd-470f-afa4-cf7e890d31b9 不是合法的 Javascript 名称。

如果名称是合法的 JavaScript 名称而不是保留字,则属性名称周围的引号是可选的。因此,“first-name”周围需要引号,但 first_name 周围是可选的。

顺便说一句,如果您如此关心 JSON 大小,为什么不 gzip 呢?

于 2011-01-27T12:55:57.057 回答
2

这是一个老问题,但如果有人在这里绊倒并想知道一种让 ALLOW_UNQUOTED_FIELD_NAMES 在较新版本的杰克逊中工作的方法,请使用:

new ObjectMapper().configure(com.fasterxml.jackson.core.JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
于 2019-12-16T01:05:29.503 回答
0

如果您正在使用Spring Boot,您可以自动装配ObjectMapper

@Configuration
public class JacksonConfig {

    @Autowired
    private ObjectMapper objectMapper;

    @PostConstruct
    public void configureObjectMapper() {
        objectMapper.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
    }
}
于 2021-02-05T11:01:56.477 回答