Jackson JSON库中的ALLOW_UNQUOTED_FIELD_NAMES

时间:2011-01-27 10:34:50

标签: java json spring parsing jackson

我正在使用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功能的特殊字符的值,可能会有任何问题吗?杰克逊会逃脱这个角色吗?

感谢。

5 个答案:

答案 0 :(得分:6)

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

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

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

答案 1 :(得分:5)

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

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

答案 2 :(得分:2)

我认为这个问题与Javascript sintax有关,而与Jackson和JSON无关。

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

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

顺便说一句,如果你对JSON大小如此关注,为什么不对它进行gzip呢?

答案 3 :(得分:0)

这是一个古老的问题,但是如果有人在这里绊倒了,想知道在新版本的杰克逊中获得ALLOW_UNQUOTED_FIELD_NAMES的方法,请使用以下方法:

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

答案 4 :(得分:0)

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

@Configuration
public class JacksonConfig {

    @Autowired
    private ObjectMapper objectMapper;

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