Comment devrais-je échapper des chaînes dans JSON?

Lors de la création manuelle de données JSON, Comment dois-je échapper des champs de chaîne? Devrais-je utiliser quelque chose comme Apache Commons Lang StringEscapeUtilities.escapeHtml, StringEscapeUtilities.escapeXml, ou devrais-je utiliser java.net.URLEncoder?

Le problème est que lorsque j'utilise SEU.escapeHtml, Il n'échappe pas aux guillemets et lorsque j'enveloppe toute la chaîne dans une paire de ' s, un JSON mal formé sera généré.

134
demandé sur Behrang 2010-06-11 07:54:16

18 réponses

Idéalement, trouvez une bibliothèque JSON dans votre langue {[9] } à laquelle vous pouvez alimenter une structure de données appropriée, et laissez-la s'inquiéter de la façon d'échapper aux choses . Il va vous garder beaucoup plus saine. Si pour une raison quelconque vous n'avez pas de bibliothèque dans votre langue, vous ne voulez pas en utiliser une (Je ne suggérerais pas this1), ou vous écrivez une bibliothèque JSON, lisez la suite.

Échapper selon la RFC. JSON est assez libéral: les seuls caractères que vous devez échapper sont \, ", et codes de contrôle (rien de moins que U + 0020).

Cette structure d'échappement est spécifique à JSON. Vous aurez besoin d'une fonction spécifique JSON. Tous les échappements peuvent être écrits comme \uXXXXXXXX est L'Unité de code UTF-161 pour ce caractère. Il y a quelques raccourcis, tels que \\, qui fonctionnent aussi bien. (Et ils se traduisent par une sortie plus petite et plus claire.)

Pour plus de détails, voir la RFC.

L'échappement de 1JSON est construit sur JS, donc il utilise \uXXXX, Où XXXX est un UTF-16 code de l'unité. Pour les points de code en dehors du BMP, cela signifie encoder des paires de Substitution, ce qui peut devenir un peu poilu. (Ou, vous pouvez simplement sortir le caractère directement, puisque JSON encodé pour est le texte Unicode, et permet ces caractères particuliers.)

138
répondu Thanatos 2014-04-22 05:44:48

Extrait De Largage :

 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();
     }
49
répondu MonoThreaded 2013-05-20 15:15:51

Essayez ceci org.codehaus.jettison.json.JSONObject.quote("your string").

Télécharger ici: http://mvnrepository.com/artifact/org.codehaus.jettison/jettison

35
répondu dpetruha 2016-04-22 11:24:10

Org.json.simple.JSONObject.escape() échappe à la citations,\, /, \r, \n, \b, \f, \t et d'autres caractères de contrôle. Il peut être utilisé pour échapper aux codes JavaScript.

import org.json.simple.JSONObject;
String test =  JSONObject.escape("your string");
22
répondu Dan-Dev 2012-07-23 10:48:00

Apache commons lang Le supporte maintenant. Assurez-vous simplement d'avoir une version assez récente D'Apache commons lang sur votre classpath. Vous aurez besoin de la version 3.2 +

Notes de version pour la version 3.2

LANG-797: ajout d'escape / unescapeJson à StringEscapeUtils.

21
répondu NS du Toit 2014-03-31 08:34:48

org.json.JSONObject quote(String data) la méthode fait le travail

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

Extrait de la documentation:

Code les données sous forme de chaîne JSON. ceci applique les guillemets et tout caractère nécessaire échappant . [...] Null sera interprété comme une chaîne vide

9
répondu I.G. Pascual 2016-10-05 11:11:04

StringEscapeUtils.escapeJavaScript / StringEscapeUtils.escapeEcmaScript devrait faire l'affaire.

6
répondu Hanubindh Krishna 2013-09-26 18:56:03

Vous ne savez pas ce que vous entendez par "création manuelle de json", mais vous pouvez utiliser quelque chose comme gson ( http://code.google.com/p/google-gson/), et cela transformerait votre HashMap, tableau, chaîne, etc., en une valeur JSON. Je recommande d'aller avec un cadre pour cela.

3
répondu Vladimir 2010-06-11 04:03:40

Si vous utilisez fastexml jackson, vous pouvez utiliser ce qui suit: com.fasterxml.jackson.core.io.JsonStringEncoder.getInstance().quoteAsString(input)

Si vous utilisez codehaus jackson, vous pouvez utiliser ce qui suit: org.codehaus.jackson.io.JsonStringEncoder.getInstance().quoteAsString(input)

3
répondu Dhiraj 2016-10-06 18:06:27

Je n'ai pas passé le temps de rendre 100% certain, mais cela a fonctionné pour mes entrées suffisamment pour être accepté par les validateurs JSON en ligne:

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

Bien qu'il ne semble pas mieux que org.codehaus.jettison.json.JSONObject.quote("your string")

J'utilise simplement des outils velocity dans mon projet déjà-mon bâtiment "JSON manuel" était dans un modèle velocity

2
répondu Tjunkie 2012-05-28 20:34:50

Pour ceux qui sont venus ici à la recherche d'une solution en ligne de commande, comme moi, --data-urlencode de cURL fonctionne bien:

curl -G -v -s --data-urlencode 'query={"type" : "/music/artist"}' 'https://www.googleapis.com/freebase/v1/mqlread'

Envoie

GET /freebase/v1/mqlread?query=%7B%22type%22%20%3A%20%22%2Fmusic%2Fartist%22%7D HTTP/1.1

, par exemple. Des données JSON plus grandes peuvent être placées dans un fichier et vous utiliserez la syntaxe @ pour spécifier un fichier à slurp dans les données à échapper. Par exemple, si

$ cat 1.json 
{
  "type": "/music/artist",
  "name": "The Police",
  "album": []
}

Vous utiliseriez

curl -G -v -s --data-urlencode query@1.json 'https://www.googleapis.com/freebase/v1/mqlread'

Et maintenant, c'est aussi un tutoriel sur la façon d'interroger Freebase à partir de la ligne de commande: -)

2
répondu vijucat 2014-11-04 03:38:52

Utilisez la classe EscapeUtils dans l'API Lang de commons.

EscapeUtils.escapeJavaScript("Your JSON string");
2
répondu Jsm 2014-11-09 11:27:50

Considérez la classejsonwriter de Moshi. Il a une API merveilleuse et il réduit la copie au minimum, Tout peut être bien diffusé à un fichier, OutputStream, etc.

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();

Si vous voulez la chaîne en main:

Buffer b = new Buffer(); // okio.Buffer
JsonWriter writer = new JsonWriter(b);
//...
String jsonString = b.readUtf8();
1
répondu orip 2015-07-21 14:21:31

Si vous devez échapper JSON dans la chaîne JSON, utilisez org.json.JSONObject.quote ("votre chaîne json qui doit être échappée") semble bien fonctionner

0
répondu webjockey 2016-10-16 04:24:08

En utilisant la syntaxe \ uXXXX peut résoudre ce problème, google UTF-16 avec le nom du signe, vous pouvez trouver XXXX, par exemple: utf-16 double quote

0
répondu David 2016-10-21 05:33:37

Les méthodes ici qui montrent l'implémentation réelle sont toutes défectueuses.
Je n'ai pas de code Java, mais juste pour Info, vous pouvez facilement convertir ce code C#:

Avec L'aimable autorisation du mono-projet @ 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();
}

Cela peut être compacté dans

    // 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
répondu Stefan Steiger 2017-04-13 09:13:58

Je pense que la meilleure réponse en 2017 est d'utiliser javax.API json. Utilisation javax.json.JsonBuilderFactory pour créer vos objets json, puis écrivez les objets à l'aide de javax.json.JsonWriterFactory. Très belle combinaison constructeur / écrivain.

0
répondu absmiths 2017-06-28 14:30:58

Apache commons-texte dispose désormais d'un StringEscapeUtils.escapeJson (chaîne) .

0
répondu Mohsen 2018-06-19 13:38:07