JavaでJSON文字列をエスケープする

JavaでJSON文字列をエスケープする

1. 概要

この短いチュートリアルでは、JavaでJSON文字列をエスケープする方法をいくつか示します。

最も人気のあるJSON処理ライブラリと、それらがどのように簡単なタスクをエスケープするかについて簡単に説明します。

2. 何が間違っているのでしょうか?

ユーザーが指定したメッセージをWebサービスに送信する単純で一般的なユースケースを考えてみましょう。 素朴に、私たちは試すかもしれません:

String payload = "{\"message\":\"" + message + "\"}";
sendMessage(payload);

しかし、実際には、これは多くの問題を引き起こす可能性があります。

最も簡単なのは、メッセージに引用が含まれている場合です。

{ "message" : "My "message" breaks json" }

さらに悪いのはthe user can knowingly break the semantics of the requestです。 彼が送信した場合:

Hello", "role" : "admin

その後、メッセージは次のようになります。

{ "message" : "Hello", "role" : "admin" }

最も簡単なアプローチは、引用符を適切なエスケープシーケンスに置き換えることです。

String payload = "{\"message\":\"" + message.replace("\"", "\\\"") + "\"}";

ただし、このアプローチは非常に脆弱です。

  • It needs to be done for every concatenated valueであり、すでにエスケープした文字列を常に念頭に置く必要があります

  • さらに、メッセージ構造は時間の経過とともに変化するため、this can become a maintenance headache

  • そしてそれはhard to read, making it even more error-proneです

簡単に言えば、より一般的なアプローチを採用する必要があります。 残念ながら、native JSON processing features are still in the JEP phaseであるため、さまざまなオープンソースのJSONライブラリに目を向ける必要があります。

幸い、severalのJSON処理ライブラリがあります。 最も人気のある3つを簡単に見てみましょう。

3. JSON-javaライブラリ

私たちのレビューで最も単純で最小のライブラリは、org.jsonとしても知られるJSON-javaです。

JSONオブジェクトを作成するには、we simply create an instance of JSONObject and basically treat it like a Map

JSONObject jsonObject = new JSONObject();
jsonObject.put("message", "Hello \"World\"");
String payload = jsonObject.toString();

これにより、「World」を引用符で囲み、エスケープします。

{
   "message" : "Hello \"World\""
}

4. ジャクソン図書館

JSON処理用の最も人気があり用途の広いJavaライブラリの1つは、Jacksonです。

一見すると、Jackson behaves similarly to org.json:

Map params = new HashMap<>();
params.put("message", "Hello \"World\"");
String payload = new ObjectMapper().writeValueAsString(params);

ただし、JacksonはJavaオブジェクトのシリアル化もサポートできます。

それでは、メッセージをカスタムクラスでラップして、例を少し拡張しましょう。

class Payload {
    Payload(String message) {
        this.message = message;
    }

    String message;

    // getters and setters
}

次に、オブジェクトのインスタンスを渡すことができるObjectMapperのインスタンスが必要です。

String payload = new ObjectMapper().writeValueAsString(new Payload("Hello \"World\""));

どちらの場合も、以前と同じ結果が得られます。

{
   "message" : "Hello \"World\""
}

すでにエスケープされたプロパティがあり、それ以上エスケープせずにシリアル化する必要がある場合は、そのフィールドでJacksonの@JsonRawValueアノテーションを使用することをお勧めします。

5. グアバ図書館

Gsonは、多くの場合goes head to head with JacksonであるGoogleのライブラリです。

もちろん、org.json againで行ったのと同じように行うことができます。

JsonObject json = new JsonObject();
json.addProperty("message", "Hello \"World\"");
String payload = new Gson().toJson(gsonObject);

または、Jacksonのようにカスタムオブジェクトを使用することもできます。

String payload = new Gson().toJson(new Payload("Hello \"World\""));

そして、再び同じ結果が得られます。

6. 結論

この短い記事では、さまざまなオープンソースライブラリを使用してJavaでJSON文字列をエスケープする方法を説明しました。

この記事に関連するすべてのコードは、over on Githubにあります。