web-dev-qa-db-ja.com

ジャクソンJSONライブラリのALLOW_UNQUOTED_FIELD_NAMES

JSONとの間でシリアル化/逆シリアル化するためにjacksonライブラリを使用しています。この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);
}

送信側プロジェクトと受信側プロジェクトの両方で、バージョン1.6.3のJacksonを使用しています。この機能に必要なバージョンは1.2以降なので、このバージョンを使用していないのではないかと思いましたが、レシーバーはSpringアプリケーションであり、libsフォルダーにインストールされているライブラリが1.6.3であることを確認しました。

何が間違っているのでしょうか?たぶん、この機能はマップでは使用できません。

別の質問があります。これまでのところ、キーが単なるuuid値で、値が数値であるマップを送信しています。 ALLOW_UNQUOTED_FIELD_NAMES機能がオンになっている特殊文字を含む値を送信すると、問題が発生する可能性がありますか?ジャクソンはこのキャラクターを脱出しますか?

ありがとう。

16
Javi

QUOTE_FIELD_NAMESを指定したJacksonのように、ALLOW_UNQUOTED_FIELD_NAMESをオンにしても自分自身を読み取れないような出力が生成される場合があります。非標準の入力解析には、おそらくカスタムJsonParserを実装する必要があります。

問題は、非標準のJSONを生成していて、クライアントがそれを適切に処理するという保証がないことです。ただし、アプリケーションの外部に公開せず、サイズを気にする場合は、Jacksonの Smile のようなバイナリ形式を解析/生成できます。 http://www.cowtowncoder.com/blog/archives/2010/09/entry_418.html (2.4)を参照してください。

5
pingw33n

わかりました、Pingw33nの答えはかなり正しいと思います。つまり、はい、この機能を使用できます。しかし、それはかなりヒューリスティックです-引用符で囲まれていない名前がどのように機能するかについての指定がないためです(結局のところ、JSONは名前にすべての文字を許可します!);または、エスケープメカニズムを使用する場合は、何を記述または受け入れるかについては誰でも推測できます。

この特定のケースでは、問題を引き起こすのはおそらく「-」文字です。これは、Jacksonが使用する近似であるJavascript名の正当な部分ではありません。

考えられる解決策の1つは、Jacksonがプロパティ名のそのような文字をエスケープすることです(現在どのように行われているのか覚えていません。名前の文字が引用されている場合)。簡単なテストケースを理解できる場合は、Jiraの拡張リクエストを Jackson Jira に提出して、エスケープを追加できます(パーサーが通常のバックスラッシュバージョンをエスケープ解除できることを確認してください)。

6
StaxMan

問題はJavascriptsintaxに関連しており、JacksonやJSONには関連していないと思います。

Javascriptでは、名前はオプションで1つ以上の文字、数字、またはアンダーバーが後に続く文字であるため、90110a2e-febd-470f-afa4-cf7e890d31b9は正式なJavascript名ではありません。

名前が予約語ではなく正当なJavaScript名である場合、プロパティ名の前後の引用符はオプションです。したがって、「first-name」の前後には引用符が必要ですが、first_nameの前後にはオプションです。

ところで、JSONサイズが気になる場合は、gzipで圧縮してみませんか?

3
Javier Ferrero

これは古い質問ですが、誰かがここでつまずいて、新しいバージョンのjacksonでALLOW_UNQUOTED_FIELD_NAMESを取得する方法を知りたい場合は、次を使用してください。

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