2010-06-11 2 views
121

При создании данных JSON вручную, как я должен избегать строковых полей? Должен ли я использовать что-то вроде Apache Commons Lang's StringEscapeUtilities.escapeHtml, StringEscapeUtilities.escapeXml или использовать java.net.URLEncoder?Как избежать строк в JSON?

Проблема заключается в том, что когда я использую SEU.escapeHtml, он не избегает кавычек, и когда я обертываю всю строку в пару ' с, генерируется некорректный JSON.

+14

Если вы завершаете всю строку парой '' ', вы обречены с самого начала: строки JSON могут быть окружены только' ''. См. Http://www.ietf.org/rfc /rfc4627.txt – Thanatos

+2

+1 для контура 'StringEscapeUtilities'. Его довольно полезно. –

ответ

130

В идеале найти библиотеку JSON на вашем языке, что вы можете кормить подходящую структуру данных для, и дайте ему беспокоиться о том, как избежать вещей. Это будет держать вас в курсе. Если по какой-либо причине у вас нет библиотеки на вашем языке, вы не хотите ее использовать (я бы не предложил это 1), или вы пишете библиотеку JSON, читайте дальше.

Побег в соответствии с RFC. JSON довольно либеральный: единственные персонажи, которых вы должны, являются: \, " и коды управления (что-то меньшее, чем U + 0020).

Эта структура экранирования специфична для JSON. Вам понадобится специальная функция JSON. Все экраны могут быть записаны как \uXXXX, где XXXX является кодовым номером UTF-16 для этого символа. Есть несколько ярлыков, таких как \\, которые также работают. (И они приводят к меньшему и более четкому выходу.)

Подробнее см. the RFC.

¹Индикация JSON построена на JS, поэтому используется \uXXXX, где XXXX - это кодовый блок UTF-16. Для кодовых точек вне BMP это означает кодирование суррогатных пар, которые могут быть немного волосатыми. (Или вы можете просто выводить символ напрямую, так как JSON закодирован для текста Unicode и позволяет использовать эти конкретные символы.)

+0

Действительно ли в JSON, как и в JavaScript, заключить строки в двойные кавычки или одинарные кавычки? Или это справедливо только для того, чтобы заключить их в двойные Кавычки? – Behrang

+7

Только двойные кавычки ('' '). – Thanatos

+0

как насчет {[]} :? – Sergei

3

Не уверен, что вы подразумеваете под «созданием json вручную», но вы можете использовать что-то вроде gson (http://code.google.com/p/google-gson/), и это превратит ваши HashMap, Array, String и т. Д. В значение JSON. Я рекомендую пойти с рамкой для этого.

+2

Ручным я имел в виду не использование библиотеки JSON, такой как Simple JSON, Gson или XStream. – Behrang

+0

Просто вопрос любопытства - почему бы вам не использовать один из этих API? Это похоже на попытку избежать URL-адресов вручную, вместо использования URLEncode/Decode ... – Vladimir

+1

Не совсем то же самое, эти библиотеки имеют гораздо больше, чем эквивалент URLEncode/Decode, они включают в себя целый пакет сериализации, позволяющий сохранить Java-объект в json-форме, а иногда вам действительно нужно только кодировать короткую связку текста – jmd

32

Попробуйте org.codehaus.jettison.json.JSONObject.quote("your string").

Скачать его здесь: http://mvnrepository.com/artifact/org.codehaus.jettison/jettison

+0

Определенно лучшее решение! Thx – Lastnico

+0

, но это не указывает на фигурные скобки, такие как [{ – Sergei

+0

@Sergei Вам не нужно скрывать фигурные скобки внутри строки JSON. – Yobert

2

я не потратил время, чтобы сделать 100% уверен, но он работал на своих входах достаточно, чтобы быть принятым онлайн JSON валидаторов:

org.apache.velocity.tools.generic.EscapeTool.EscapeTool().java("input") 

хотя это делает не выглядит лучше, чем org.codehaus.jettison.json.JSONObject.quote("your string")

Я просто использовать инструменты скорости в моем проекте уже - мой «руководство в формате JSON» здание в шаблоне скорости

22

org.json.simple.JSONObject.escape() выполняет кавычки, \, /, \ r, \ n, \ b, \ f, \ t и другие управляющие символы. Он может использоваться для исключения кодов JavaScript.

import org.json.simple.JSONObject; 
String test = JSONObject.escape("your string"); 
+3

Это зависит от библиотеки json, которую вы используете (JSONObject.escape, JSONObject.quote, ..), но это всегда статический метод, выполняющий задание кавычек и просто нужно повторно использовать – amine

+0

Какая библиотека является частью org.json? У меня нет этого в моем классе. –

+0

https://github.com/fangyidong/json-simple/tree/master/src/main/java/org/json/simple см. Https://code.google.com/archive/p/json-simple/ –

46

Экстракт из Jettison:

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(); 
    } 
+1

Примечание: Это Java –

+5

Ну, это был тег OP – MonoThreaded

+0

Не понимайте только, когда c <'', перейдите в \ u. В моем случае есть символ \ uD38D, который равен 55357 и более '', поэтому не меняется на \ u ... – Stony

6

StringEscapeUtils.escapeJavaScript/StringEscapeUtils.escapeEcmaScript должен сделать трюк тоже.

+7

'escapeJavaScript' выводит одинарные кавычки как' \ '', что неверно. – laurt

19

Apache commons lang теперь поддерживает это. Просто убедитесь, что у вас есть достаточно недавняя версия общих прав Apache на вашем пути к классам. Вы будете нуждаться в версии 3.2+

Заметки о выпуске для версии 3.2

LANG-797: Добавлено побег/unescapeJson в StringEscapeUtils.

+0

Это самый практичный ответ для меня. Большинство проектов уже используют apache commons lang, поэтому нет необходимости добавлять зависимость для одной функции. Вероятно, лучшим вариантом будет JSON-строитель. – absmiths

+0

В качестве продолжения, и потому, что я не могу понять, как отредактировать комментарий, я добавил новый, я нашел javax.json.JsonObjectBuilder и javax.json.JsonWriter. Очень приятная комбинация застройщиков/писателей. – absmiths

2

Для тех, кто пришел сюда в поисках решения командной строки, как я, --data-UrlEncode Curl работает отлично:

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 могут быть помещены в файл, и вы должны использовать синтаксис @, чтобы указать файл, который будет обрабатывать данные, которые будут сбрасываться. Например, если

$ 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 из командной строки :-)

класса
3

Использование EscapeUtils в Commons lang API.

EscapeUtils.escapeJavaScript("Your JSON string"); 
+2

JavaScript! == JSON –

+1

Обратите внимание, что одинарные кавычки, например, обрабатываются по-разному при выходе из javascript или json. В commons.lang 3.4 StringEscapeUtils (https://commons.apache.org/proper/commons-lang/javadocs/api-3.4/org/apache/commons/lang3/StringEscapeUtils.html#escapeJson(java.lang.String)) имеет метод escapeJSON, который отличается от метода escapeJavaScript в обычном режиме.lang 2: https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/StringEscapeUtils.html#escapeJavaScript(java.lang.String) – GlennV

1

Рассмотрим Moshi «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(); 
0

Методы здесь, которые показывают, что фактическая реализация все неисправна.
У меня нет 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(); 
    } 
} 
+0

Как работает ' quote() 'метод, описанный в других ответах, неисправен? – Sandy

7

org.json.JSONObjectquote(String data) метод делает работу

import org.json.JSONObject; 
String jsonEncodedString = JSONObject.quote(data); 

Выдержка из документации:

кодирует данные в виде строки JSON. Это применимо к котировкам и любому ненужному экранированию символов. [...] Null будет интерпретироваться как пустая строка

+1

'org.apache.sling.commons.json.JSONObject' также имеет эту же вещь –

2

Если вы используете fastexml Джексон, вы можете использовать следующее: com.fasterxml.jackson.core.io.JsonStringEncoder.getInstance().quoteAsString(input)

Если вы используете Codehaus Джексон, вы можете использовать следующий : org.codehaus.jackson.io.JsonStringEncoder.getInstance().quoteAsString(input)

0

Если вам нужно бежать JSON внутри JSON строки, используйте org.json.JSONObject.quote («ваш JSON строку, которая должна быть экранированы»), кажется, хорошо

0

работать, используя \ ихххх синтаксис Калифорния n решить эту проблему, google UTF-16 с именем знака, вы можете узнать XXXX, например: utf-16 double quote

0

Я думаю, что лучшим ответом в 2017 году является использование API javax.json. Используйте javax.json.JsonBuilderFactory для создания ваших json-объектов, а затем создайте объекты с помощью javax.json.JsonWriterFactory. Очень приятная комбинация застройщиков/писателей.

Смежные вопросы