1. Обзор
В этом кратком руководстве мы покажем несколько способов экранирования строки JSON в Java.
Мы совершим краткий обзор самых популярных библиотек для обработки JSON и того, как с их помощью избежать простой задачи.
2. Что может пойти не так?
Давайте рассмотрим простой, но распространенный случай отправки указанного пользователем сообщения в веб-службу. Наивно, мы могли бы попробовать:
String payload = "{\"message\":\"" + message + "\"}";
sendMessage(payload);
Но, на самом деле, это может создать много проблем.
Самое простое, если сообщение содержит цитату:
{ "message" : "My "message" breaks json" }
Хуже того, пользователь может намеренно нарушить семантику запроса . Если он посылает:
Hello", "role" : "admin
Тогда сообщение становится:
{ "message" : "Hello", "role" : "admin" }
Самый простой подход — заменить кавычки соответствующей escape-последовательностью:
String payload = "{\"message\":\"" + message.replace("\"", "\\\"") + "\"}";
Однако этот подход довольно хрупок:
- Это необходимо сделать для каждого конкатенированного значения , и нам нужно всегда помнить, какие строки мы уже экранировали.
- Более того, поскольку структура сообщения со временем меняется, это может стать головной болью при обслуживании.
- И это трудно читать, что делает его еще более подверженным ошибкам .
Проще говоря, нам нужно использовать более общий подход. К сожалению, нативные функции обработки JSON все еще находятся на стадии JEP , поэтому нам придется обратить внимание на различные библиотеки JSON с открытым исходным кодом.
К счастью, существует несколько библиотек обработки JSON. Давайте кратко рассмотрим три самых популярных из них.
3. Библиотека JSON-java
Самая простая и маленькая библиотека в нашем обзоре — это JSON-java, также известная как org.json
.
Чтобы создать объект JSON, мы просто создаем экземпляр JSONObject
и в основном обрабатываем его как карту
:
JSONObject jsonObject = new JSONObject();
jsonObject.put("message", "Hello \"World\"");
String payload = jsonObject.toString();
Это возьмет кавычки вокруг «World» и избежит их:
{
"message" : "Hello \"World\""
}
4. Библиотека Джексона
Одна из самых популярных и универсальных библиотек Java для обработки JSON — Jackson .
На первый взгляд Джексон ведет себя аналогично org.json
:
Map<String, Object> params = new HashMap<>();
params.put("message", "Hello \"World\"");
String payload = new ObjectMapper().writeValueAsString(params);
Однако Джексон также может поддерживать сериализацию объектов 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\""
}
В тех случаях, когда у нас есть уже экранированное свойство и нам нужно сериализовать его без дальнейшего экранирования, мы можем захотеть использовать аннотацию Джексона @JsonRawValue
для этого поля.
5. Библиотека Гсона
Gson — это библиотека от Google, которая часто конкурирует с Jackson .
Мы можем, конечно, снова сделать то, что мы сделали с org.json
:
JsonObject json = new JsonObject();
json.addProperty("message", "Hello \"World\"");
String payload = new Gson().toJson(gsonObject);
Или мы можем использовать пользовательские объекты, как с Джексоном:
String payload = new Gson().toJson(new Payload("Hello \"World\""));
И снова получим тот же результат.
6. Заключение
В этой короткой статье мы увидели, как экранировать строки JSON в Java, используя различные библиотеки с открытым исходным кодом.
Весь код, относящийся к этой статье, можно найти на Github .