Как я должен экранировать строки в JSON?



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



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

2145   18  

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 будет интерпретироваться как пустая строка

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

Не уверен, что вы подразумеваете под "созданием 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 из командной строки : -)

используйте класс EscapeUtils в API commons lang.

EscapeUtils.escapeJavaScript("Your JSON string");

считают Моши ' 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

    Ничего не найдено.