jackon JSON库中的允许未引用字段名称

ca1c2owp  于 2023-01-22  发布在  其他
关注(0)|答案(6)|浏览(139)

我正在使用jackson库进行JSON的序列化/反序列化。我需要这个JSON具有尽可能小的大小,所以我启用了ALLOW_UNQUOTED_FIELD_NAMES功能来消除所有引号。我知道删除引号不是标准json,但使json变小是项目的一个硬性要求。生成的json工作正常,但当我试图读取json值时,我遇到了一个异常:
org.codehaus.jackson.JsonParseException:意外字符('9 '(代码57)):字段名的开头应为有效的名称字符(对于不带引号的名称)或双引号(对于带引号的名称)[源:字符串读取器@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>>() {});

我用来读写这些值的对象Map器是:

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

我使用的是1.6.3版本的Jackson,在发送器和接收器项目中。这个功能所需的版本是1.2+,所以我想也许我没有使用这个版本,但我的接收器是一个Spring应用程序,我已经检查了安装在libs文件夹中的库是1.6.3。
我可能做错了什么?也许这个功能不能和Map一起使用。
我还有另一个问题,到目前为止,我只是发送了一个Map,其中的键只是一个uuid值,而值是一个数字。如果我发送了一个带有特殊字符的值,并且打开了ALLOW_UNQUOTED_FIELD_NAMES功能,会有什么问题吗?jackson会转义这些字符吗?
谢谢。

fykwrbwg

fykwrbwg1#

好的,我认为Pingw 33 n的答案非常正确。是的,您可以使用该功能;但它是相当启发式的--因为没有规范说明不带引号的名称应该如何工作(毕竟,JSON允许名称使用任何字符!);或者,如果要使用任何转义机制,那么任何人都可以猜测应该编写或接受什么。
在这种特殊情况下,可能是“-”字符导致了问题。它不是Javascript名称的法律的部分,这是Jackson使用的近似值。
一个可能的解决方案是Jackson在属性名中转义这样的字符(我不记得目前是怎么做的;如果你能想出一个简单的测试用例,你可以在Jackson Jira上提交一个Jira增强请求来添加转义(并确保解析器可以取消常用的反斜杠版本)。

cxfofazt

cxfofazt2#

看起来Jackson在某些情况下使用QUOTE_FIELD_NAMES会产生这样的输出,即使使用ALLOW_UNQUOTED_FIELD_NAMES,它也不能读取自己。您可能需要为非标准输入解析实现自定义JsonParser
问题是你生成的是非标准的JSON,不能保证客户端能正确处理它,但是如果你不把它暴露在你的应用程序之外,并且非常关心它的大小,你可以解析/生成像Jackson的Smile这样的二进制格式,参见http://www.cowtowncoder.com/blog/archives/2010/09/entry_418.html(2.4)。

jfgube3f

jfgube3f3#

我相信这个问题与Javascript sintax有关,而与Jackson和JSON无关。
在Javascript中,名称是一个字母,后面可以跟一个或多个字母、数字或下划线,因此90110 a2 e-febd-470 f-afa 4-cf 7 e890 d31 b 9不是法律的的Javascript名称。
如果属性名称是法律的的JavaScript名称而不是保留字,则属性名称周围的引号是可选的。因此,“first-name”周围需要引号,但first_name周围的引号是可选的。
顺便说一句,如果你这么关心JSON的大小,为什么不gzip呢?

aij0ehis

aij0ehis4#

这是一个老问题,但是如果有人在这里遇到了问题,并且想知道一种方法来让ALLOW_UNQUOTED_FIELD_NAMES在较新版本的Jackson中工作,请使用以下命令:

new ObjectMapper().configure(com.fasterxml.jackson.core.JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
inb24sb2

inb24sb25#

如果您使用的是Spring Boot,则可以自动连接ObjectMapper

@Configuration
public class JacksonConfig {

    @Autowired
    private ObjectMapper objectMapper;

    @PostConstruct
    public void configureObjectMapper() {
        objectMapper.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
    }
}
gudnpqoy

gudnpqoy6#

以防有人查到:在新版本的Jackson中,有JsonMapper.builder()。所有尝试摆弄objectMapper.deserializationConfig的尝试对我来说都失败了。这起作用了:

ObjectMapper objectMapper = JsonMapper.builder()
        .enable(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES)
        // other "enable(...) calls"
        .build();

相关问题