मुझे JSON में तार कैसे बचना चाहिए?


154

मैन्युअल रूप से JSON डेटा बनाते समय, मुझे स्ट्रिंग फ़ील्ड से कैसे बचना चाहिए? चाहिए मैं कुछ की तरह अपाचे कॉमन्स लैंग की उपयोग StringEscapeUtilities.escapeHtml, StringEscapeUtilities.escapeXml, या मैं इस्तेमाल करना चाहिए java.net.URLEncoder?

समस्या यह है कि जब मैं उपयोग SEU.escapeHtmlकरता हूं , तो यह उद्धरणों से बच नहीं जाता है और जब मैं पूरी स्ट्रिंग को 'एस की जोड़ी में लपेटता हूं , तो एक विकृत JSON उत्पन्न होगा।


20
यदि आप एक जोड़ी में पूरे स्ट्रिंग को लपेट रहे हैं ', तो आप शुरू से ही बर्बाद हो रहे हैं: JSON के तार केवल साथ ही घिरे हो सकते हैं "Ietf.org/rfc/rfc4627.txt देखें ।
थानाटोस

2
StringEscapeUtilitiesरूपरेखा के लिए +1 । यह बहुत उपयोगी है।
मुहम्मद गेल्बाना

जवाबों:


157

आदर्श रूप से, अपनी भाषा में एक JSON लाइब्रेरी ढूंढें जिसे आप कुछ उपयुक्त डेटा संरचना खिला सकते हैं, और यह चिंता करने दें कि चीजों को कैसे बचाना है । यह आपको बहुत पवित्र रखेगा। यदि किसी भी कारण से आपकी भाषा में पुस्तकालय नहीं है, तो आप एक का उपयोग नहीं करना चाहते हैं (मैं यह सुझाव नहीं दूंगा), या आप एक JSON लाइब्रेरी लिख रहे हैं, पर पढ़ें।

इसे RFC के अनुसार एस्केप करें। JSON बहुत उदार है: केवल वे वर्ण जो आप करना चाहिए से बचने के हैं \, "और नियंत्रण कोड (कुछ भी U + 0020 से कम)।

भागने की यह संरचना JSON के लिए विशिष्ट है। आपको एक JSON विशिष्ट फ़ंक्शन की आवश्यकता होगी। पलायन के सभी के रूप में लिखा जा सकता है \uXXXX, जहां XXXXकि चरित्र के लिए UTF-16 कोड unit¹ है। कुछ शॉर्टकट हैं, जैसे कि \\, जो काम भी करते हैं। (और वे एक छोटे और स्पष्ट उत्पादन में परिणाम हैं।)

पूर्ण विवरण के लिए, RFC देखें ।

SoJSON का एस्केपिंग JS पर बनाया गया है, इसलिए यह यूटीएफ -16 कोड यूनिट है \uXXXX, जहां इसका उपयोग किया XXXXजाता है। बीएमपी के बाहर कोड बिंदुओं के लिए, इसका अर्थ है सरोगेट जोड़े को एन्कोड करना, जो थोड़ा बालों वाला हो सकता है। (या, आप सीधे चरित्र का उत्पादन कर सकते हैं, क्योंकि JSON के लिए यूनिकोड पाठ को इनकोड किया गया है, और ये विशेष वर्णों को अनुमति देता है।)


क्या यह जावास्क्रिप्ट में JSON में मान्य है, डबल कोट्स या सिंगल कोट्स में स्ट्रिंग्स संलग्न करने के लिए? या क्या उन्हें केवल दोहरे उद्धरण चिह्नों में संलग्न करना मान्य है?
बेहरंग सईदज़ादेह

14
केवल दोहरे उद्धरण ( ")।
थानाटोस

3
@ सर्गी: पात्रों {[]}:?को एक बैकस्लैश के साथ बच नहीं जाना चाहिए। ( \:उदाहरण के लिए, JSON स्ट्रिंग में मान्य नहीं है।) उन सभी को वैकल्पिक रूप \uXXXXसे कई बाइट्स की बर्बादी पर सिंटैक्स का उपयोग करके बचाया जा सकता है । RFC का §2.5 देखें।
थानाटोस

2
मुझे यकीन नहीं है कि यह कितना व्यापक रूप से समर्थित है, लेकिन मेरे अनुभव JSON.stringify()में नौकरी करने के लिए एक कॉल है ।
रास

2
@ बिटकॉइलर एक यूनिकोड चरित्र बिल्कुल भी अस्पष्ट नहीं है - इसका मतलब यह है कि इसमें यूनिकोड युक्ति में एक कोड बिंदु (या अंक) है। जब आप std :: string का उपयोग करते हैं, तो यह यूनिकोड वर्णों का एक समूह होता है। जब आपको इसे क्रमांकित करने की आवश्यकता होती है, तो किसी फ़ाइल या नेटवर्क पर कहने की अनुमति देता है, तो वह है कि 'कौन सा एन्कोडिंग' आता है। यह थानाटोस के अनुसार लगता है कि वे चाहते हैं कि आप यूटीएफ का उपयोग करें, लेकिन तकनीकी रूप से किसी भी एन्कोडिंग का उपयोग तब तक किया जा सकता है जब तक कि इसे यूनिकोड वर्णों में पुनर्गठित किया जा सकता है।
जेरार्ड ओनील

54

जेटीसन से निकालें :

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

10
खैर, यह ओपी टैग था
मोनोअथ्रेडेड

केवल तभी समझ में नहीं आता जब c <'', \ u में बदलें। मेरे मामले में, चरित्र \ uD38D है, जो 55357 और '' पर है, इसलिए \ u में नहीं बदलता ...
Stony

1
@ स्टोनी एक नए प्रश्न की तरह लगता है
मोनोअथ्रेडेड

@MonoThreaded आपके उत्तर के लिए धन्यवाद, मुझे अभी भी पता नहीं क्यों। लेकिन अंत में, मैंने इसे ठीक करने के लिए विधि बदल दी, अगर (c <'' || c> 0x7f) {t = "000" + Integer.toHexString (c) .toUpperCase (); sb.append ("\\ u" + t.substring (t.length () - 4)); } और {sb.append (c); }}
Stony

1
@Stony, सभी के अलावा अन्य पात्रों ", \ , और नियंत्रण वर्ण (से पहले "" उन) लंबे उत्पादन एन्कोडिंग के रूप में मैचों के रूप में मान्य अंदर JSON तार कर रहे हैं। दूसरे शब्दों में, \uD38Dजब तक UTF एन्कोडिंग संरक्षित है , आपको "words" को एनकोड करने की आवश्यकता नहीं है।
meustrus

37

यह कोशिश करो org.codehaus.jettison.json.JSONObject.quote("your string")

इसे यहाँ डाउनलोड करें: http://mvnrepository.com/artifact/org.codehaus.jettison/jettison


निश्चित रूप से सबसे अच्छा समाधान! Thx
Lastnico

लेकिन यह
सर्गेई

1
@ शेर्ज़ी आपको जेएसएन स्ट्रिंग के अंदर ब्रेसिज़ से बचना नहीं है।
योबर्ट

यह दिखाने के लिए उपयोगी हो सकता है कि यह वास्तव में क्या लौटाता है।
ट्रेवर

2
org.json.JSONObject.quote ("आपका json string") भी ठीक काम करता है
webjockey

23

org.json.simple.JSONObject.escape () उद्धरण, \, /, \ r, \ n, \ b, \ f, \ t और अन्य नियंत्रण वर्ण से बच जाता है। इसका उपयोग जावास्क्रिप्ट कोड से बचने के लिए किया जा सकता है।

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

3
यह आपके द्वारा उपयोग किए जा रहे json लाइब्रेरी पर निर्भर करता है (JSONObject.escape, JSONObject.quote, ..) लेकिन यह हमेशा एक स्थिर विधि है जो उद्धृत कार्य कर रही है और बस पुन: उपयोग किया जाना चाहिए
amine

कौन सा पुस्तकालय org.json का हिस्सा है? मेरे पास मेरे वर्गपथ पर नहीं है।
एलेक्स स्पर्लिंग


22

Apache commons lang अब इसका समर्थन करता है। बस सुनिश्चित करें कि आपके पास अपने क्लासपाथ पर हाल ही में अपाचे कॉमन्स लैंग का पर्याप्त संस्करण है। आपको संस्करण 3.2+ की आवश्यकता होगी

संस्करण 3.2 के लिए नोट्स जारी करें

LANG-797: StringEscapeUtils में जोड़ा गया एस्केप / अनस्केपस्केप।


यह मेरे लिए सबसे व्यावहारिक जवाब है। अधिकांश परियोजनाएं पहले से ही अपाचे कॉमन्स लैंग का उपयोग करती हैं, इसलिए एक फ़ंक्शन के लिए निर्भरता जोड़ने की कोई आवश्यकता नहीं है। एक JSON बिल्डर शायद सबसे अच्छा जवाब होगा।
अनुपस्थित

एक अनुवर्ती के रूप में, और क्योंकि मैं समझ नहीं पा रहा हूं कि एक टिप्पणी को संपादित करने के लिए कैसे मैंने एक नया जोड़ा, मुझे javax.json.JsonObjectBuilder और javax.json.JsonWriter मिला। बहुत अच्छा बिल्डर / लेखक संयोजन।
अनुपस्थित

1
यह अपाचे कॉमन्स लैंग में पदावनत है, आपको अपाचे कॉमन्स टेक्स्ट का उपयोग करने की आवश्यकता है । अफसोस की बात है कि यह पुस्तकालय /पात्रों से बचकर वैकल्पिक / पुरानी कल्पना का पालन करता है । यह JSON सहित बहुत सी चीजों को तोड़ता है जिसमें URL शामिल हैं। मूल प्रस्ताव /से बचने के लिए एक विशेष चार के रूप में था, लेकिन अब ऐसा नहीं है, जैसा कि हम लेखन के समय नवीनतम कल्पना
adamnfish

10

org.json.JSONObject quote(String data) तरीका काम करता है

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

प्रलेखन से निकालें:

डेटा को JSON स्ट्रिंग के रूप में एन्कोड करता है। यह उद्धरण और किसी भी आवश्यक चरित्र से बचने के लिए लागू होता है । [...] नल की व्याख्या एक रिक्त स्ट्रिंग के रूप में की जाएगी


1
org.apache.sling.commons.json.JSONObject यह भी एक ही बात है
जॉर्डन Shurmer


4

यदि आप फास्टेक्स एमएल जैकसन का उपयोग कर रहे हैं, तो आप निम्नलिखित का उपयोग कर सकते हैं: com.fasterxml.jackson.core.io.JsonStringEncoder.getInstance().quoteAsString(input)

यदि आप कोडहॉस जैकसन का उपयोग कर रहे हैं, तो आप निम्नलिखित का उपयोग कर सकते हैं: org.codehaus.jackson.io.JsonStringEncoder.getInstance().quoteAsString(input)


3

सुनिश्चित नहीं है कि "मैन्युअल रूप से json बनाने" से आपका क्या मतलब है, लेकिन आप gson ( http://code.google.com/p/google-gson/ ) जैसी किसी चीज़ का उपयोग कर सकते हैं , और यह आपके HashMap, Array, String, आदि को रूपांतरित कर देगा। , JSON मान के लिए। मैं इसके लिए एक ढांचे के साथ जाने की सलाह देता हूं।


2
मैन्युअल रूप से मेरा मतलब साधारण JSON, Gson या XStream जैसी JSON लाइब्रेरी का उपयोग करने से नहीं था।
बेहरंग सईदज़ादेह

बस एक जिज्ञासा की बात है - आप इनमें से किसी एक एपीआई का उपयोग क्यों नहीं करना चाहेंगे? यह URLEncode / Decode का उपयोग करने के बजाय मैन्युअल रूप से URL से बचने की कोशिश करने जैसा है ...
व्लादिमीर

1
वास्तव में समान नहीं है, वे पुस्तकालय URLEncode / Decode के बराबर से बहुत अधिक के साथ आते हैं, वे json रूप में जावा ऑब्जेक्ट की दृढ़ता की अनुमति देने के लिए एक संपूर्ण क्रमांकन पैकेज शामिल करते हैं, और कभी-कभी आपके वास्तव में केवल पाठ का एक छोटा गुच्छा सांकेतिक शब्दों में बदलना चाहिए
jmd

2
JSON का एक मैनुअल बनाने से समझ में आता है, यदि आप डेटा के छोटे बिट्स को क्रमबद्ध करने के लिए सिर्फ एक लाइब्रेरी को शामिल नहीं करना चाहते हैं
आदित्य कुमार पांडे

2
मैं किसी भी परियोजना से एक टीम के सदस्य को हटाने के लिए कहूंगा, अगर वे JSON को मैन्युअल रूप से बनाने की हिम्मत करते हैं जहां ऐसा करने के लिए एक उच्च गुणवत्ता वाली लाइब्रेरी मौजूद थी।
माइकल जॉयस

2

मैंने 100% निश्चित करने के लिए समय नहीं बिताया है, लेकिन इसने मेरे इनपुट के लिए काम किया है जो ऑनलाइन JSON सत्यापनकर्ताओं द्वारा स्वीकार किए जाने के लिए पर्याप्त है:

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

हालांकि यह किसी से बेहतर नहीं दिखता है org.codehaus.jettison.json.JSONObject.quote("your string")

मैं अपने प्रोजेक्ट में पहले से ही वेलोसिटी टूल्स का उपयोग करता हूं - मेरी "मैनुअल JSON" बिल्डिंग एक वेग टेम्पलेट के भीतर थी


2

जो लोग मेरे लिए कमांड-लाइन समाधान की तलाश में यहां आए थे, मेरे जैसे, 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 query@1.json 'https://www.googleapis.com/freebase/v1/mqlread'

और अब, यह भी एक ट्यूटोरियल है कि कमांड लाइन से फ्रीबेस को कैसे क्वेरी करें :-)


2

कॉमन्स लैंग एपीआई में एस्केपयूटिल्स क्लास का उपयोग करें।

EscapeUtils.escapeJavaScript("Your JSON string");

1
ध्यान दें कि उदाहरण के लिए एकल उद्धरण अलग तरह से संभाले जाते हैं जब जावास्क्रिप्ट या जसन से बचकर निकलते हैं। Commons.lang 3.4 StringEscapeUtils ( commons.apache.org/proper/commons-lang/javadocs/api-3.4/org/… ) में एक एस्केपजॉन विधि है, जो commons.lang 2: commons.apache
-2.6

1

मोशी के JsonWriter वर्ग पर विचार करें । इसमें एक अद्भुत एपीआई है और यह एक न्यूनतम पर कॉपी करना कम कर देता है, सब कुछ अच्छी तरह से एक दायर, आउटपुटस्ट्रीम, आदि के लिए स्ट्रीम किया जा सकता है।

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

यदि आपको JSON स्ट्रिंग के अंदर JSON से बचने की आवश्यकता है, तो org.json.JSONObject.quote का उपयोग करें ("आपका जस स्ट्रिंग जिसे भागने की आवश्यकता है") अच्छी तरह से काम करने लगती हैं


0

\ uXXXX सिंटैक्स का उपयोग करके इस समस्या को हल किया जा सकता है, साइन के नाम के साथ Google UTF-16, आप XXXX का पता लगा सकते हैं, उदाहरण के लिए: utf-16 डबल उद्धरण


0

यहां जो तरीके वास्तविक कार्यान्वयन को दर्शाते हैं वे सभी दोषपूर्ण हैं।
मेरे पास जावा कोड नहीं है, लेकिन सिर्फ रिकॉर्ड के लिए, आप इस C # -code को आसानी से बदल सकते हैं:

मोनो-प्रोजेक्ट के सौजन्य से @ 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();
    }
}

quote()अन्य उत्तरों में वर्णित विधि दोषपूर्ण कैसे है ?
सैंडी

0

मुझे लगता है कि 2017 में सबसे अच्छा उत्तर javax.json API का उपयोग करना है। अपने jSON ऑब्जेक्ट्स बनाने के लिए javax.json.JsonBuilderFactory का उपयोग करें, फिर javax.json.JsonWriterFactory का उपयोग करके ऑब्जेक्ट लिखें। बहुत अच्छा बिल्डर / लेखक संयोजन।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.