jackon JSON 库中的 ALLOW_UNQUOTED_FIELD_NAMES
我正在使用 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 功能的情况下发送包含特殊字符的值,可能会遇到任何问题吗?杰克逊会逃脱这个角色吗?
谢谢。
I'm using the jackson library for serializing/deserializing to/from JSON. I need that this JSON has the smallest size as possible so I've enabled the feature ALLOW_UNQUOTED_FIELD_NAMES to eliminate all the quotes. I know that removing quotes is not standard json, but making json small is a hard requirement of the project. The generated json works, but when I've trying to read the json value I'm getting an exception:
org.codehaus.jackson.JsonParseException:
Unexpected character ('9' (code 57)):
was expecting either valid name
character (for unquoted name) or
double-quote (for quoted) to start
field name at [Source:
java.io.StringReader@1347d75; line: 1,
column: 3]
The exception above is thrown when I read this json:
{90110a2e-febd-470f-afa4-cf7e890d31b9:0,eec652ad-a4d9-4eb1-8d24-7c1a0c29449f:1}
The way I read it is:
Map<String, Object> valuesMap = oM.readValue(json, new TypeReference<Map<String, Object>>() {});
and the object mapper I use both for reading and writing the values is:
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);
}
I'm using version 1.6.3 of Jackson, in both the sender and the receiver projects. The needed version for this feature is 1.2+ so I thought that maybe I wasn't using this version, but my receiver is a Spring application and I've checked that the library installed in libs folder is 1.6.3.
What may I be doing wrong? Maybe this feature cannot be used with maps.
I have another question, So far I'm just sending a map where the key is just a uuid value and the value is a number. May I have any problems if I send a value with special characters with ALLOW_UNQUOTED_FIELD_NAMES feature on? Will jackson escape this characters?
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
好吧,我认为 Pingw33n 的答案非常正确。所以:是的,您可以使用该功能;但这是相当启发式的——因为没有关于不带引号的名称应该如何工作的规范(毕竟,JSON 允许名称中的任何和所有字符!);或者,如果要使用任何转义机制,任何人都可以猜测应该编写或接受什么。
在这种特殊情况下,可能是“-”字符导致了问题。它不是 Javascript 名称的合法部分,这是 Jackson 使用的近似值。
一种可能的解决方案是杰克逊在属性名称中转义这些字符(我不记得目前是如何完成的;如果引用了任何名称字符)。如果您能找出一个简单的测试用例,您可以在 Jackson Jira 添加转义(并确保解析器可以转义通常的反斜杠版本)。
Ok, Pingw33n's answer is pretty much correct I think. So: yes, you can use the feature; but it is rather heuristic -- since there is no specification as to how unquoted names should work (after all, JSON allows any and all characters for names!); or, what if any escape mechanism is to be used, it's anyone's guess as to what should be written or accepted.
In this particular case it is probably '-' character that causes an issue. It is not a legal part of Javascript name, which is the approximation Jackson uses.
One possible solution would be for Jackson to escape such characters in property names (I don't remember how it is done currently; if any name characters are quoted). If you can figure out a simple test case, you can file a Jira request-for-enchancement at Jackson Jira to get escaping added (and ensure parser can unescape the usual backslash version).
似乎杰克逊在某些情况下使用
QUOTE_FIELD_NAMES
会产生这样的输出,即使打开ALLOW_UNQUOTED_FIELD_NAMES
,它也无法读取自身。您可能需要实现自定义 JsonParser 来进行非标准输入解析。问题是您正在生成非标准 JSON,并且不能保证客户端能够正确处理它。但是,如果您不将其暴露在应用程序之外并且非常关心大小,您可以解析/生成二进制格式,例如 Jackson 的 微笑。请参阅http://www.cowtowncoder.com/blog/archives/2010/ 09/entry_418.html (2.4)。
Seems like Jackson with
QUOTE_FIELD_NAMES
in certain cases produces such output that it can't read itself even withALLOW_UNQUOTED_FIELD_NAMES
on. You will probably need to implement customJsonParser
for non-standard input parsing.The problem is that you're generating non-standard JSON and there's no guarantees that client will handle it properly. However if you don't expose it outside your application(s) and care about size much you could parse/generate binary format like Jackson's Smile. See http://www.cowtowncoder.com/blog/archives/2010/09/entry_418.html (2.4).
我相信这个问题与 Javascript sintax 有关,而不是与 Jackson 或 JSON 有关。
在 Javascript 中,名称是一个字母,可选后跟一个或多个字母、数字或下划线,因此 90110a2e-febd-470f-afa4-cf7e890d31b9 不是合法的 Javascript 名称。
如果属性名称是合法的 JavaScript 名称而不是保留字,则属性名称周围的引号是可选的。因此,“名字”周围需要引号,但名字周围的引号是可选的。
顺便说一句,如果您如此关心 JSON 大小,为什么不对其进行 gzip 压缩呢?
I believe the problem is related to Javascript sintax and not to Jackson nor JSON.
In Javascript a name is a letter optionally followed by one or more letters, digits, or underbars, so 90110a2e-febd-470f-afa4-cf7e890d31b9 is not a legal Javascript name.
The quotes around a property's name are optional if the name would be a legal JavaScript name and not a reserved word. So quotes are required around "first-name", but are optional around first_name.
BTW, if you are so concerned about JSON size why don't you gzip it?
这是一个老问题,但如果有人在这里绊倒并想知道一种方法让 ALLOW_UNQUOTED_FIELD_NAMES 在较新版本的 jackson 中工作,请使用以下命令:
This is an old question, but if anyone stumbles here and wants to know a way to get ALLOW_UNQUOTED_FIELD_NAMES work in newer versions of jackson, use this:
如果您使用的是
Spring Boot
,则可以自动装配ObjectMapper
:If you're using
Spring Boot
, you can autowire theObjectMapper
:如果有人正在查找这个:在较新版本的 Jackson 中,有
JsonMapper.builder()
。对我来说,所有摆弄 objectMapper.deserializationConfig 的尝试都失败了。这有效:In case somebody is looking this up: in newer versions of Jackson, there's the
JsonMapper.builder()
. All attempts at fiddling with theobjectMapper.deserializationConfig
have failed for me. This worked: