Как мне избежать строк в JSON?

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

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

Ответ 1

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

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

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

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

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

Ответ 2

Извлечь из 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();
     }

Ответ 4

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

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

Ответ 5

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

Примечания к выпуску для версии 3.2

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

Ответ 6

org.json.JSONObject quote(String data) метод выполняет задание

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

Извлеките из документации:

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

Ответ 7

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

Ответ 8

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

Ответ 9

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

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

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

Я просто использую инструменты скорости в моем проекте уже - мое "руководство JSON" было в пределах шаблона скорости

Ответ 10

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

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

Ответ 11

Использовать класс EscapeUtils в общедоступном API.

EscapeUtils.escapeJavaScript("Your JSON string");

Ответ 12

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

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

Ответ 13

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

Ответ 14

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

Ответ 15

используя синтаксис \uXXXX, можно решить эту проблему, google UTF-16 с именем знака, вы можете узнать XXXX, например: двойная кавычка utf-16

Ответ 16

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

Ответ 18

Методы здесь, которые показывают фактическую реализацию, все неисправны.

У меня нет Java-кода, но только для записи вы можете легко преобразовать этот С# -код:

Предоставлено монопроектом @ 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();
    }
}