Как я должен экранировать строки в JSON?
при создании данных JSON вручную, как я должен экранировать строковые поля? Я должен использовать что-то вроде Apache Commons Lang's StringEscapeUtilities.escapeHtml,StringEscapeUtilities.escapeXml, или я должен использовать java.net.URLEncoder?
проблема в том, что когда я использую SEU.escapeHtml, он не экранирует кавычки и когда я обертываю всю строку в пару 's, будет сгенерирован искаженный JSON.
18 ответов:
в идеале, найти библиотеку JSON на вашем языке что вы можете кормить некоторые соответствующие структуры данных,и пусть он беспокоится о том, как избежать вещей. Это поможет тебе сохранить рассудок. Если по какой-либо причине у вас нет библиотеки на вашем языке, вы не хотите ее использовать (я бы не предложил это1), или вы пишете библиотеку JSON, читайте дальше.
избежать его в соответствии с RFC. JSON довольно либеральный: только символы вы должны побег - это
\,", и управляющие коды (что-нибудь меньшее, чем U+0020).эта структура экранирования специфична для JSON. Вам понадобится специальная функция JSON. Все побеги могут быть записаны как
\uXXXXздесьXXXXявляется UTF-16 код unit1 для этого символа. Есть несколько ярлыков, таких как\, которые также работают. (И они приводят к меньшему и более четкому выходу.)для получения более подробной информации см. RFC.
1JSON по escaping построен на JS, поэтому он использует
\uXXXX, гдеXXXXблок кода UTF-16. Для кодовых точек за пределами BMP это означает кодирование суррогатных пар, которые могут стать немного волосатыми. (Или вы можете просто вывести символ напрямую, так как кодировка JSON для текста Unicode и позволяет эти конкретные символы.)
Выписка Из сбросить:
public static String quote(String string) { if (string == null || string.length() == 0) { return "\"\""; } char c = 0; int i; int len = string.length(); StringBuilder sb = new StringBuilder(len + 4); String t; sb.append('"'); for (i = 0; i < len; i += 1) { c = string.charAt(i); switch (c) { case '\': case '"': sb.append('\'); sb.append(c); break; case '/': // if (b == '<') { sb.append('\'); // } sb.append(c); break; case '\b': sb.append("\b"); break; case '\t': sb.append("\t"); break; case '\n': sb.append("\n"); break; case '\f': sb.append("\f"); break; case '\r': sb.append("\r"); break; default: if (c < ' ') { t = "000" + Integer.toHexString(c); sb.append("\u" + t.substring(t.length() - 4)); } else { sb.append(c); } } } sb.append('"'); return sb.toString(); }
попробуй такое
org.codehaus.jettison.json.JSONObject.quote("your string").загрузите его здесь:http://mvnrepository.com/artifact/org.codehaus.jettison/jettison
org.формат JSON.простой.JSONObject.escape () экранирует кавычки,\,/, \r, \n, \b, \f, \t и другие управляющие символы. Он может быть использован для экранирования кодов JavaScript.
import org.json.simple.JSONObject; String test = JSONObject.escape("your string");
Apache commons lang теперь поддерживает это. Просто убедитесь, что у вас есть достаточно недавняя версия Apache commons lang на вашем пути к классам. Вам понадобится версия 3.2+
примечания к выпуску для версии 3.2
LANG-797: добавлен escape / unescapeJson в StringEscapeUtils.
org.json.JSONObjectquote(String data)метод делает работуimport org.json.JSONObject; String jsonEncodedString = JSONObject.quote(data);выдержка из документации:
кодирует данные в виде строки JSON. это относится кавычки и любой необходимый символ экранирования. [...] Null будет интерпретироваться как пустая строка
Не уверен, что вы подразумеваете под "созданием json вручную", но вы можете использовать что-то вроде gson (http://code.google.com/p/google-gson/), и это преобразует ваш HashMap, массив, строку и т. д. В значение JSON. Я рекомендую пойти с рамками для этого.
Если вы используете fastexml jackson, вы можете использовать следующее:
com.fasterxml.jackson.core.io.JsonStringEncoder.getInstance().quoteAsString(input)Если вы используете codehaus jackson, вы можете использовать следующее:
org.codehaus.jackson.io.JsonStringEncoder.getInstance().quoteAsString(input)
Я не потратил время, чтобы убедиться на 100%, но он работал для моих входов достаточно, чтобы быть принятым онлайн-валидаторами JSON:
org.apache.velocity.tools.generic.EscapeTool.EscapeTool().java("input")хотя это выглядит не лучше, чем
org.codehaus.jettison.json.JSONObject.quote("your string")Я просто использую инструменты скорости в своем проекте уже - мое" ручное JSON " здание было в шаблоне скорости
для тех, кто пришел сюда в поисках решения командной строки, как и я, curl's --data-urlencode отлично работает:
curl -G -v -s --data-urlencode 'query={"type" : "/music/artist"}' 'https://www.googleapis.com/freebase/v1/mqlread'передает
GET /freebase/v1/mqlread?query=%7B%22type%22%20%3A%20%22%2Fmusic%2Fartist%22%7D HTTP/1.1, например. Большие данные JSON могут быть помещены в файл, и вы будете использовать синтаксис@, чтобы указать файл для slurp в подлежащих экранированию данных. Например, если
$ cat 1.json { "type": "/music/artist", "name": "The Police", "album": [] }вы могли бы использовать
curl -G -v -s --data-urlencode [email protected] 'https://www.googleapis.com/freebase/v1/mqlread'и теперь, это также учебник о том, как запросить Freebase из командной строки : -)
считают Моши ' s JsonWriter класса. Он имеет замечательный API, и он сводит копирование к минимуму, все может быть красиво передано в файл, OutputStream и т. д.
OutputStream os = ...; JsonWriter json = new JsonWriter(Okio.buffer(Okio.sink(os))); json.beginObject(); json.name("id").value(getId()); json.name("scores"); json.beginArray(); for (Double score : getScores()) { json.value(score); } json.endArray(); json.endObject();Если вы хотите строку в руке:
Buffer b = new Buffer(); // okio.Buffer JsonWriter writer = new JsonWriter(b); //... String jsonString = b.readUtf8();
Если вам нужно избежать JSON внутри строки JSON, используйте org.формат JSON.JSONObject.цитата ("ваша строка json, которая должна быть экранирована"), похоже, работает хорошо
используя синтаксис \uXXXX можно решить эту проблему, google UTF-16 С именем знака, вы можете узнать XXXX, например: utf-16 двойная кавычка
методы здесь, которые показывают фактическую реализацию, все неисправны.
У меня нет кода Java, но только для записи, вы можете легко конвертировать этот C# - код:любезно предоставлено моно-проектом @ https://github.com/mono/mono/blob/master/mcs/class/System.Web/System.Web/HttpUtility.cs
public static string JavaScriptStringEncode(string value, bool addDoubleQuotes) { if (string.IsNullOrEmpty(value)) return addDoubleQuotes ? "\"\"" : string.Empty; int len = value.Length; bool needEncode = false; char c; for (int i = 0; i < len; i++) { c = value[i]; if (c >= 0 && c <= 31 || c == 34 || c == 39 || c == 60 || c == 62 || c == 92) { needEncode = true; break; } } if (!needEncode) return addDoubleQuotes ? "\"" + value + "\"" : value; var sb = new System.Text.StringBuilder(); if (addDoubleQuotes) sb.Append('"'); for (int i = 0; i < len; i++) { c = value[i]; if (c >= 0 && c <= 7 || c == 11 || c >= 14 && c <= 31 || c == 39 || c == 60 || c == 62) sb.AppendFormat("\u{0:x4}", (int)c); else switch ((int)c) { case 8: sb.Append("\b"); break; case 9: sb.Append("\t"); break; case 10: sb.Append("\n"); break; case 12: sb.Append("\f"); break; case 13: sb.Append("\r"); break; case 34: sb.Append("\\""); break; case 92: sb.Append("\\"); break; default: sb.Append(c); break; } } if (addDoubleQuotes) sb.Append('"'); return sb.ToString(); }Это можно сжать в
// https://github.com/mono/mono/blob/master/mcs/class/System.Json/System.Json/JsonValue.cs public class SimpleJSON { private static bool NeedEscape(string src, int i) { char c = src[i]; return c < 32 || c == '"' || c == '\' // Broken lead surrogate || (c >= '\uD800' && c <= '\uDBFF' && (i == src.Length - 1 || src[i + 1] < '\uDC00' || src[i + 1] > '\uDFFF')) // Broken tail surrogate || (c >= '\uDC00' && c <= '\uDFFF' && (i == 0 || src[i - 1] < '\uD800' || src[i - 1] > '\uDBFF')) // To produce valid JavaScript || c == '\u2028' || c == '\u2029' // Escape "</" for <script> tags || (c == '/' && i > 0 && src[i - 1] == '<'); } public static string EscapeString(string src) { System.Text.StringBuilder sb = new System.Text.StringBuilder(); int start = 0; for (int i = 0; i < src.Length; i++) if (NeedEscape(src, i)) { sb.Append(src, start, i - start); switch (src[i]) { case '\b': sb.Append("\b"); break; case '\f': sb.Append("\f"); break; case '\n': sb.Append("\n"); break; case '\r': sb.Append("\r"); break; case '\t': sb.Append("\t"); break; case '\"': sb.Append("\\""); break; case '\': sb.Append("\\"); break; case '/': sb.Append("\/"); break; default: sb.Append("\u"); sb.Append(((int)src[i]).ToString("x04")); break; } start = i + 1; } sb.Append(src, start, src.Length - start); return sb.ToString(); } }
Я думаю, что лучший ответ в 2017 году использовать javax.API в формате JSON. Использовать javax.формат JSON.JsonBuilderFactory для создания объектов json, а затем записать объекты с помощью javax.формат JSON.JsonWriterFactory. Очень хорошая комбинация строитель / писатель.
Apache commons-текст теперь имеет StringEscapeUtils.escapeJson (String).
Comments