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