C # में JSON फॉर्मैटर?


101

एक फ़ंक्शन की तलाश है जो stringइनपुट के रूप में Json को ले जाएगा और इसे लाइन ब्रेक और इंडेंटेशन के साथ प्रारूपित करेगा। सत्यापन एक बोनस होगा, लेकिन यह आवश्यक नहीं है, और मुझे इसे किसी वस्तु या किसी भी चीज़ में पार्स करने की आवश्यकता नहीं है।

किसी को भी ऐसी लाइब्रेरी का पता है?


नमूना इनपुट:

{"status":"OK", "results":[ {"types":[ "locality", "political"], "formatted_address":"New York, NY, USA", "address_components":[ {"long_name":"New York", "short_name":"New York", "types":[ "locality", "political"]}, {"long_name":"New York", "short_name":"New York", "types":[ "administrative_area_level_2", "political"]}, {"long_name":"New York", "short_name":"NY", "types":[ "administrative_area_level_1", "political"]}, {"long_name":"United States", "short_name":"US", "types":[ "country", "political"]}], "geometry":{"location":{"lat":40.7143528, "lng":-74.0059731}, "location_type":"APPROXIMATE", "viewport":{"southwest":{"lat":40.5788964, "lng":-74.2620919}, "northeast":{"lat":40.8495342, "lng":-73.7498543}}, "bounds":{"southwest":{"lat":40.4773990, "lng":-74.2590900}, "northeast":{"lat":40.9175770, "lng":-73.7002720}}}}]} 

जवाबों:


123

मैंने पुराने संस्करण को अपडेट किया, अब इसे पूर्णांक और बूलियन जैसे निर्विवाद मूल्यों का समर्थन करना चाहिए।

मैंने पिछले संस्करण को फिर से तैयार किया और अंतिम संस्करण प्राप्त किया: कोड छोटा और क्लीनर है। केवल एक विस्तार विधि की आवश्यकता है। सबसे महत्वपूर्ण: कुछ कीड़े तय।

class JsonHelper
{
    private const string INDENT_STRING = "    ";
    public static string FormatJson(string str)
    {
        var indent = 0;
        var quoted = false;
        var sb = new StringBuilder();
        for (var i = 0; i < str.Length; i++)
        {
            var ch = str[i];
            switch (ch)
            {
                case '{':
                case '[':
                    sb.Append(ch);
                    if (!quoted)
                    {
                        sb.AppendLine();
                        Enumerable.Range(0, ++indent).ForEach(item => sb.Append(INDENT_STRING));
                    }
                    break;
                case '}':
                case ']':
                    if (!quoted)
                    {
                        sb.AppendLine();
                        Enumerable.Range(0, --indent).ForEach(item => sb.Append(INDENT_STRING));
                    }
                    sb.Append(ch);
                    break;
                case '"':
                    sb.Append(ch);
                    bool escaped = false;
                    var index = i;
                    while (index > 0 && str[--index] == '\\')
                        escaped = !escaped;
                    if (!escaped)
                        quoted = !quoted;
                    break;
                case ',':
                    sb.Append(ch);
                    if (!quoted)
                    {
                        sb.AppendLine();
                        Enumerable.Range(0, indent).ForEach(item => sb.Append(INDENT_STRING));
                    }
                    break;
                case ':':
                    sb.Append(ch);
                    if (!quoted)
                        sb.Append(" ");
                    break;
                default:
                    sb.Append(ch);
                    break;
            }
        }
        return sb.ToString();
    }
}

static class Extensions
{
    public static void ForEach<T>(this IEnumerable<T> ie, Action<T> action)
    {
        foreach (var i in ie)
        {
            action(i);
        }
    }
}

ओह .. मैं अपने पुराने संस्करण को देख रहा था। ओह अच्छा। अभी भी अच्छा है: डी जाहिर है मैं एक जवाब पर अभी तक स्वीकार नहीं किया था, इसलिए जीजे! आप चेक करवा लें।
मपेन जू

तुम्हारा एक मामूली बग को छोड़कर बहुत अच्छा है: "url":"url('http://google.com')"प्रारूप करने के लिए "url":"url('http : //google.com')"। दूसरे के पहले और बाद में रिक्त स्थान जोड़े जाते हैं ":" जो गलत है।
पीटर लॉन्ग

क्या यह वास्तव में पूर्णांक जैसे अनछुए मूल्यों पर काम कर रहा है?
जोहान डैनफोर्थ

@JohanDanforth - एक बार जब मैंने लाइन # 64 ("अगर (उद्धृत)" बिट) हटा दी तो लगता है कि यह मेरे लिए अयोग्य मूल्यों के साथ ठीक काम कर रहा है।
१०:१० पर जेरेटेट

क्यों नहीं एक नई विधि बनाने .ToList()के IEnumerableबजाय पर उपयोग करें ? आप उपयोग कर रहे हैं MoreLinqअपनी परियोजना में, यह भी समर्थन करेंगे .ForEach()पर IEnumerableबॉक्स से बाहर।
केहलान क्रुममे

123

आप इसके लिए Newtonsoft.Json लाइब्रेरी का भी उपयोग कर सकते हैं और फ़ॉर्मेटिंग के साथ SerializeObject को कॉल कर सकते हैं।

var x = JsonConvert.SerializeObject(jsonString, Formatting.Indented);

दस्तावेज़ीकरण: एक वस्तु को सीरियल करें


अपडेट करें -

बस फिर से कोशिश की। बहुत यकीन है कि यह काम करता था - शायद यह बाद के संस्करण में बदल गया या शायद मैं सिर्फ चीजों की कल्पना कर रहा हूं। वैसे भी, नीचे दी गई टिप्पणियों के अनुसार, यह अपेक्षा के अनुरूप काम नहीं करता है। हालांकि, ये (सिर्फ लिनकैप में परीक्षण किया गया) हैं। पहली टिप्पणी से है, दूसरा एक उदाहरण है जो मैंने SO में कहीं और पाया है -

void Main()
{
    //Example 1
    var t = "{\"x\":57,\"y\":57.0,\"z\":\"Yes\"}";
    var obj = Newtonsoft.Json.JsonConvert.DeserializeObject(t); 
    var f = Newtonsoft.Json.JsonConvert.SerializeObject(obj, Newtonsoft.Json.Formatting.Indented);
    Console.WriteLine(f);

    //Example 2
    JToken jt = JToken.Parse(t);
    string formatted = jt.ToString(Newtonsoft.Json.Formatting.Indented);
    Console.WriteLine(formatted);

    //Example 2 in one line -
    Console.WriteLine(JToken.Parse(t).ToString(Newtonsoft.Json.Formatting.Indented));
}

8
विंस - सच है, लेकिन अगर आप ऐसा करने जा रहे हैं, तो इसका मतलब है कि आप शायद अन्य JSON सामान भी करने जा रहे हैं और यदि ऐसा है तो इसका मतलब होगा। यदि नहीं, तो भी मैं तर्क दूंगा कि यह अपने स्वयं के सुंदर प्रिंटर को ज्यादातर मामलों में रोल करने से बेहतर है क्योंकि ऐसा करने के लिए अधिक प्रयास की आवश्यकता होती है :)
फ्रैंक टेज़ाबेटिस

6
यह काम नहीं करता। एक स्ट्रिंग को सीरियल करना जो पहले से ही इस तरह से जस का तस है, इसे सुशोभित नहीं किया जाएगा, यहां तक ​​कि फ़ॉर्मेटिंग के साथ भी। यह केवल स्ट्रिंग को उद्धृत करता है, और सभी मौजूदा उद्धरणों से बच जाता है।
रोस

रॉस - क्या आपने इसे आज़माया है? जब आप Formatting.Indented विकल्प का उपयोग करते हैं, तो यह JSON स्ट्रिंग को "सुंदर प्रिंट" करता है।
फ्रैंक टिज़ाबेटिस

8
मैंने ऊपर कोड की कोशिश की, और एक ही (गलत) परिणाम प्राप्त किया - मेरे लिए ठीक था: var obj = JsonConvert.DeserializeObject(jsonString); var formatted = JsonConvert.SerializeObject(obj, Formatting.Indented) (यानी एक अस्थायी वस्तु में विलोपन, फिर वापस json में) - वास्तव में सबसे कुशल तरीका नहीं है, लेकिन यह कम से कम काम किया!
benjymous

59

Json.net लाइब्रेरी के लिए छोटा नमूना।

using Newtonsoft.Json;

private static string format_json(string json)
{
    dynamic parsedJson = JsonConvert.DeserializeObject(json);
    return JsonConvert.SerializeObject(parsedJson, Formatting.Indented);
}

PS: आप फॉर्मेट किए गए json टेक्स्ट को टैग के साथ प्रिंट करने के लिए रैप कर सकते हैं क्योंकि यह html पेज पर है।


मेरे लिए newtonsoft.Json संस्करण 6.
Rocklan

Newtonsoft.Json संस्करण 10.0.3 के साथ अच्छी तरह से काम करता है। Win10 Intel i7-7700 CPU (4.20Ghz) पर 5 सेकंड से कम समय में 6MB JSON फ़ाइल बनाई।
बैटपॉक्स

35

यहां JSON ब्यूटिफायर का एक कॉम्पैक्ट संस्करण है।

private const string INDENT_STRING = "    ";

static string FormatJson(string json) {

    int indentation = 0;
    int quoteCount = 0;
    var result = 
        from ch in json
        let quotes = ch == '"' ? quoteCount++ : quoteCount
        let lineBreak = ch == ',' && quotes % 2 == 0 ? ch + Environment.NewLine +  String.Concat(Enumerable.Repeat(INDENT_STRING, indentation)) : null
        let openChar = ch == '{' || ch == '[' ? ch + Environment.NewLine + String.Concat(Enumerable.Repeat(INDENT_STRING, ++indentation)) : ch.ToString()
        let closeChar = ch == '}' || ch == ']' ? Environment.NewLine + String.Concat(Enumerable.Repeat(INDENT_STRING, --indentation)) + ch : ch.ToString()
        select lineBreak == null    
                    ? openChar.Length > 1 
                        ? openChar 
                        : closeChar
                    : lineBreak;

    return String.Concat(result);
}

आउटपुट:

 {
    "status":"OK",
     "results":[
         {
            "types":[
                 "locality",
                 "political"
            ],
             "formatted_address":"New York, NY, USA",
             "address_components":[
                 {
                    "long_name":"New York",
                     "short_name":"New York",
                     "types":[
                         "locality",
                         "political"
                    ]
                },
                 {
                    "long_name":"New York",
                     "short_name":"New York",
                     "types":[
                         "administrative_area_level_2",
                         "political"
                    ]
                },
                 {
                    "long_name":"New York",
                     "short_name":"NY",
                     "types":[
                         "administrative_area_level_1",
                         "political"
                    ]
                },
                 {
                    "long_name":"United States",
                     "short_name":"US",
                     "types":[
                         "country",
                         "political"
                    ]
                }
            ],
             "geometry":{
                "location":{
                    "lat":40.7143528,
                     "lng":-74.0059731
                },
                 "location_type":"APPROXIMATE",
                 "viewport":{
                    "southwest":{
                        "lat":40.5788964,
                         "lng":-74.2620919
                    },
                     "northeast":{
                        "lat":40.8495342,
                         "lng":-73.7498543
                    }
                },
                 "bounds":{
                    "southwest":{
                        "lat":40.4773990,
                         "lng":-74.2590900
                    },
                     "northeast":{
                        "lat":40.9175770,
                         "lng":-73.7002720
                    }
                }
            }
        }
    ]
}

2
आउटपुट हर दूसरी पंक्ति पर 1 स्थान से बंद है, और यह कॉलोन के बाद कुछ स्थान का उपयोग कर सकता है।
मप्र

6
मुझे विश्वास नहीं हो रहा है कि @Vince_Panucio के उत्तर में केवल 3 अपवोट प्राप्त हुए हैं? यह शुद्ध प्रतिभा है। उसके लाइन कोड को लें और विज़ुअल स्टूडियो में पेस्ट करें, फिर उसे रीसेंपर का उपयोग करके इसे एक विधि श्रृंखला में परिवर्तित करें, यह देखने के लिए कि आप सामान्य का उपयोग करके एक ही चीज़ कैसे लिखेंगे। चयन (x ...) चुनें (y) और यह कुछ है। लंबे पृष्ठ। अच्छा किया विंस, ... बहुत अच्छा किया!
स्नोडकोड

1
उत्कृष्ट शिल्प कौशल के लिए +1। जितना मुझे यह पसंद है, उतने (साझा) उत्पादन कोड के लिए, मैं इसे शायद विभाजित कर दूंगा और पठनीयता / डिबगैबिलिटी के लिए फॉरच लूप में बदल दूंगा।
3dGrabber

1
@ अतिरिक्त स्थान अल्पविराम के बाद और मूल इनपुट में उद्धरण से पहले दिखाई देता है। तो, आपके इनपुट के आधार पर, ymmv।
जेसी चिशोल्म

1
यह बिल्कुल सही नहीं है, बेझिझक इसे अपने प्रोजेक्ट में ठीक कर सकते हैं
रेजर

8

और भी सरल जो मैंने लिखा था:

public class JsonFormatter
{
    public static string Indent = "    ";

    public static string PrettyPrint(string input)
    {
        var output = new StringBuilder(input.Length * 2);
        char? quote = null;
        int depth = 0;

        for(int i=0; i<input.Length; ++i)
        {
            char ch = input[i];

            switch (ch)
            {
                case '{':
                case '[':
                    output.Append(ch);
                    if (!quote.HasValue)
                    {
                        output.AppendLine();
                        output.Append(Indent.Repeat(++depth));
                    }
                    break;
                case '}':
                case ']':
                    if (quote.HasValue)  
                        output.Append(ch);
                    else
                    {
                        output.AppendLine();
                        output.Append(Indent.Repeat(--depth));
                        output.Append(ch);
                    }
                    break;
                case '"':
                case '\'':
                    output.Append(ch);
                    if (quote.HasValue)
                    {
                        if (!output.IsEscaped(i))
                            quote = null;
                    }
                    else quote = ch;
                    break;
                case ',':
                    output.Append(ch);
                    if (!quote.HasValue)
                    {
                        output.AppendLine();
                        output.Append(Indent.Repeat(depth));
                    }
                    break;
                case ':':
                    if (quote.HasValue) output.Append(ch);
                    else output.Append(" : ");
                    break;
                default:
                    if (quote.HasValue || !char.IsWhiteSpace(ch)) 
                        output.Append(ch);
                    break;
            }
        }

        return output.ToString();
    }
}

आवश्यक एक्सटेंशन:

    public static string Repeat(this string str, int count)
    {
        return new StringBuilder().Insert(0, str, count).ToString();
    }

    public static bool IsEscaped(this string str, int index)
    {
        bool escaped = false;
        while (index > 0 && str[--index] == '\\') escaped = !escaped;
        return escaped;
    }

    public static bool IsEscaped(this StringBuilder str, int index)
    {
        return str.ToString().IsEscaped(index);
    }

नमूना उत्पादन:

{
    "status" : "OK",
    "results" : [
        {
            "types" : [
                "locality",
                "political"
            ],
            "formatted_address" : "New York, NY, USA",
            "address_components" : [
                {
                    "long_name" : "New York",
                    "short_name" : "New York",
                    "types" : [
                        "locality",
                        "political"
                    ]
                },
                {
                    "long_name" : "New York",
                    "short_name" : "New York",
                    "types" : [
                        "administrative_area_level_2",
                        "political"
                    ]
                },
                {
                    "long_name" : "New York",
                    "short_name" : "NY",
                    "types" : [
                        "administrative_area_level_1",
                        "political"
                    ]
                },
                {
                    "long_name" : "United States",
                    "short_name" : "US",
                    "types" : [
                        "country",
                        "political"
                    ]
                }
            ],
            "geometry" : {
                "location" : {
                    "lat" : 40.7143528,
                    "lng" : -74.0059731
                },
                "location_type" : "APPROXIMATE",
                "viewport" : {
                    "southwest" : {
                        "lat" : 40.5788964,
                        "lng" : -74.2620919
                    },
                    "northeast" : {
                        "lat" : 40.8495342,
                        "lng" : -73.7498543
                    }
                },
                "bounds" : {
                    "southwest" : {
                        "lat" : 40.4773990,
                        "lng" : -74.2590900
                    },
                    "northeast" : {
                        "lat" : 40.9175770,
                        "lng" : -73.7002720
                    }
                }
            }
        }
    ]
}

एक छोटा बग: "url":"url('http://google.com')"प्रारूपित किया जाएगा "url":"url('http : //google.com')"
पीटर लॉन्ग

6

यहाँ पहले से ही शानदार उत्तरों का एक समूह है जो न्यूटनसॉफ्ट का उपयोग करते हैं। जेएसएन , लेकिन यहां एक और अधिक है जो JObject.Parseसंयोजन के साथ उपयोग करता है ToString(), क्योंकि अभी तक इसका उल्लेख नहीं किया गया है:

var jObj = Newtonsoft.Json.Linq.JObject.Parse(json);
var formatted = jObj.ToString(Newtonsoft.Json.Formatting.Indented);

इसका उत्तर होना चाहिए .. केवल दो लाइनें केवल उस स्थिति के लिए, जब आपका चर json एक json-object हो; अन्यथा तर्क विफल हो सकता है यदि तर्क एक सरणी, स्ट्रिंग, अशक्त आदि है ..
joedotnot

6

मैं बहुत कॉम्पैक्ट से बहुत प्रभावित थे JSON संरूपक द्वारा विन्स Panuccio
यहाँ एक बेहतर संस्करण है जिसका अब मैं उपयोग करता हूँ:

public static string FormatJson(string json, string indent = "  ")
{
    var indentation = 0;
    var quoteCount = 0;
    var escapeCount = 0;

    var result =
        from ch in json ?? string.Empty
        let escaped = (ch == '\\' ? escapeCount++ : escapeCount > 0 ? escapeCount-- : escapeCount) > 0
        let quotes = ch == '"' && !escaped ? quoteCount++ : quoteCount
        let unquoted = quotes % 2 == 0
        let colon = ch == ':' && unquoted ? ": " : null
        let nospace = char.IsWhiteSpace(ch) && unquoted ? string.Empty : null
        let lineBreak = ch == ',' && unquoted ? ch + Environment.NewLine + string.Concat(Enumerable.Repeat(indent, indentation)) : null
        let openChar = (ch == '{' || ch == '[') && unquoted ? ch + Environment.NewLine + string.Concat(Enumerable.Repeat(indent, ++indentation)) : ch.ToString()
        let closeChar = (ch == '}' || ch == ']') && unquoted ? Environment.NewLine + string.Concat(Enumerable.Repeat(indent, --indentation)) + ch : ch.ToString()
        select colon ?? nospace ?? lineBreak ?? (
            openChar.Length > 1 ? openChar : closeChar
        );

    return string.Concat(result);
}

यह निम्नलिखित समस्याओं को हल करता है:

  1. तार के अंदर अनुक्रम बच
  2. बृहदान्त्र के बाद रिक्त स्थान गुम
  3. अल्पविराम (या कहीं और) के बाद अतिरिक्त स्थान
  4. तार और घुंघराले लट के अंदर तार
  5. शून्य इनपुट पर विफल नहीं होता है

आउटपुट:

{
  "status": "OK",
  "results": [
    {
      "types": [
        "locality",
        "political"
      ],
      "formatted_address": "New York, NY, USA",
      "address_components": [
        {
          "long_name": "New York",
          "short_name": "New York",
          "types": [
            "locality",
            "political"
          ]
        },
        {
          "long_name": "New York",
          "short_name": "New York",
          "types": [
            "administrative_area_level_2",
            "political"
          ]
        },
        {
          "long_name": "New York",
          "short_name": "NY",
          "types": [
            "administrative_area_level_1",
            "political"
          ]
        },
        {
          "long_name": "United States",
          "short_name": "US",
          "types": [
            "country",
            "political"
          ]
        }
      ],
      "geometry": {
        "location": {
          "lat": 40.7143528,
          "lng": -74.0059731
        },
        "location_type": "APPROXIMATE",
        "viewport": {
          "southwest": {
            "lat": 40.5788964,
            "lng": -74.2620919
          },
          "northeast": {
            "lat": 40.8495342,
            "lng": -73.7498543
          }
        },
        "bounds": {
          "southwest": {
            "lat": 40.4773990,
            "lng": -74.2590900
          },
          "northeast": {
            "lat": 40.9175770,
            "lng": -73.7002720
          }
        }
      }
    }
  ]
}

3

अपने स्वयं के फ़ंक्शन को लिखने का मुख्य कारण यह है कि JSON फ्रेमवर्क आमतौर पर स्ट्रिंग के पार्सिंग को .net प्रकारों में करते हैं और उन्हें वापस स्ट्रिंग में परिवर्तित करते हैं, जिसके परिणामस्वरूप मूल तार खो सकते हैं। उदाहरण के लिए 0.0002 2E-4 हो जाता है

मैं अपने कार्य को पोस्ट नहीं करता (यह अन्य के समान ही सुंदर है) लेकिन यहाँ परीक्षण के मामले हैं

using System.IO;

using Newtonsoft.Json;

using NUnit.Framework;

namespace json_formatter.tests
{
    [TestFixture]
    internal class FormatterTests
    {
        [Test]
        public void CompareWithNewtonsofJson()
        {
            string file = Path.Combine(TestContext.CurrentContext.TestDirectory, "json", "minified.txt");

            string json = File.ReadAllText(file);

            string newton = JsonPrettify(json);
            // Double space are indent symbols which newtonsoft framework uses
            string my = new Formatter("  ").Format(json);

            Assert.AreEqual(newton, my);
        }

        [Test]
        public void EmptyArrayMustNotBeFormatted()
        {
            var input = "{\"na{me\": []}";
            var expected = "{\r\n\t\"na{me\": []\r\n}";

            Assert.AreEqual(expected, new Formatter().Format(input));
        }

        [Test]
        public void EmptyObjectMustNotBeFormatted()
        {
            var input = "{\"na{me\": {}}";
            var expected = "{\r\n\t\"na{me\": {}\r\n}";

            Assert.AreEqual(expected, new Formatter().Format(input));
        }

        [Test]
        public void MustAddLinebreakAfterBraces()
        {
            var input = "{\"name\": \"value\"}";
            var expected = "{\r\n\t\"name\": \"value\"\r\n}";

            Assert.AreEqual(expected, new Formatter().Format(input));
        }

        [Test]
        public void MustFormatNestedObject()
        {
            var input = "{\"na{me\":\"val}ue\", \"name1\": {\"name2\":\"value\"}}";
            var expected = "{\r\n\t\"na{me\": \"val}ue\",\r\n\t\"name1\": {\r\n\t\t\"name2\": \"value\"\r\n\t}\r\n}";

            Assert.AreEqual(expected, new Formatter().Format(input));
        }

        [Test]
        public void MustHandleArray()
        {
            var input = "{\"name\": \"value\", \"name2\":[\"a\", \"b\", \"c\"]}";
            var expected = "{\r\n\t\"name\": \"value\",\r\n\t\"name2\": [\r\n\t\t\"a\",\r\n\t\t\"b\",\r\n\t\t\"c\"\r\n\t]\r\n}";
            Assert.AreEqual(expected, new Formatter().Format(input));
        }

        [Test]
        public void MustHandleArrayOfObject()
        {
            var input = "{\"name\": \"value\", \"name2\":[{\"na{me\":\"val}ue\"}, {\"nam\\\"e2\":\"val\\\\\\\"ue\"}]}";
            var expected =
                "{\r\n\t\"name\": \"value\",\r\n\t\"name2\": [\r\n\t\t{\r\n\t\t\t\"na{me\": \"val}ue\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"nam\\\"e2\": \"val\\\\\\\"ue\"\r\n\t\t}\r\n\t]\r\n}";
            Assert.AreEqual(expected, new Formatter().Format(input));
        }

        [Test]
        public void MustHandleEscapedString()
        {
            var input = "{\"na{me\":\"val}ue\", \"name1\": {\"nam\\\"e2\":\"val\\\\\\\"ue\"}}";
            var expected = "{\r\n\t\"na{me\": \"val}ue\",\r\n\t\"name1\": {\r\n\t\t\"nam\\\"e2\": \"val\\\\\\\"ue\"\r\n\t}\r\n}";
            Assert.AreEqual(expected, new Formatter().Format(input));
        }

        [Test]
        public void MustIgnoreEscapedQuotesInsideString()
        {
            var input = "{\"na{me\\\"\": \"val}ue\"}";
            var expected = "{\r\n\t\"na{me\\\"\": \"val}ue\"\r\n}";

            Assert.AreEqual(expected, new Formatter().Format(input));
        }

        [TestCase(" ")]
        [TestCase("\"")]
        [TestCase("{")]
        [TestCase("}")]
        [TestCase("[")]
        [TestCase("]")]
        [TestCase(":")]
        [TestCase(",")]
        public void MustIgnoreSpecialSymbolsInsideString(string symbol)
        {
            string input = "{\"na" + symbol + "me\": \"val" + symbol + "ue\"}";
            string expected = "{\r\n\t\"na" + symbol + "me\": \"val" + symbol + "ue\"\r\n}";

            Assert.AreEqual(expected, new Formatter().Format(input));
        }

        [Test]
        public void StringEndsWithEscapedBackslash()
        {
            var input = "{\"na{me\\\\\": \"val}ue\"}";
            var expected = "{\r\n\t\"na{me\\\\\": \"val}ue\"\r\n}";

            Assert.AreEqual(expected, new Formatter().Format(input));
        }

        private static string PrettifyUsingNewtosoft(string json)
        {
            using (var stringReader = new StringReader(json))
            using (var stringWriter = new StringWriter())
            {
                var jsonReader = new JsonTextReader(stringReader);
                var jsonWriter = new JsonTextWriter(stringWriter)
                                {
                                    Formatting = Formatting.Indented
                                };
                jsonWriter.WriteToken(jsonReader);
                return stringWriter.ToString();
            }
        }
    }
}

2

आप को छोड़ करने की आवश्यकता है \rऔर \nमें PrettyPrint()। आउटपुट मज़ेदार लगता है कि वहाँ कुछ पहले से मौजूद हैं (या स्रोत पहले से ही स्वरूपित था)।


2

तय किया ... कुछ हद तक।

public class JsonFormatter
{
    #region class members
    const string Space = " ";
    const int DefaultIndent = 0;
    const string Indent = Space + Space + Space + Space;
    static readonly string NewLine = Environment.NewLine;
    #endregion

    private enum JsonContextType
    {
        Object, Array
    }

    static void BuildIndents(int indents, StringBuilder output)
    {
        indents += DefaultIndent;
        for (; indents > 0; indents--)
            output.Append(Indent);
    }


    bool inDoubleString = false;
    bool inSingleString = false;
    bool inVariableAssignment = false;
    char prevChar = '\0';

    Stack<JsonContextType> context = new Stack<JsonContextType>();

    bool InString()
    {
        return inDoubleString || inSingleString;
    }

    public string PrettyPrint(string input)
    {
        var output = new StringBuilder(input.Length * 2);
        char c;

        for (int i = 0; i < input.Length; i++)
        {
            c = input[i];

            switch (c)
            {
                case '{':
                    if (!InString())
                    {
                        if (inVariableAssignment || (context.Count > 0 && context.Peek() != JsonContextType.Array))
                        {
                            output.Append(NewLine);
                            BuildIndents(context.Count, output);
                        }
                        output.Append(c);
                        context.Push(JsonContextType.Object);
                        output.Append(NewLine);
                        BuildIndents(context.Count, output);
                    }
                    else
                        output.Append(c);

                    break;

                case '}':
                    if (!InString())
                    {
                        output.Append(NewLine);
                        context.Pop();
                        BuildIndents(context.Count, output);
                        output.Append(c);
                    }
                    else
                        output.Append(c);

                    break;

                case '[':
                    output.Append(c);

                    if (!InString())
                        context.Push(JsonContextType.Array);

                    break;

                case ']':
                    if (!InString())
                    {
                        output.Append(c);
                        context.Pop();
                    }
                    else
                        output.Append(c);

                    break;

                case '=':
                    output.Append(c);
                    break;

                case ',':
                    output.Append(c);

                    if (!InString() && context.Peek() != JsonContextType.Array)
                    {
                        BuildIndents(context.Count, output);
                        output.Append(NewLine);
                        BuildIndents(context.Count, output);
                        inVariableAssignment = false;
                    }

                    break;

                case '\'':
                    if (!inDoubleString && prevChar != '\\')
                        inSingleString = !inSingleString;

                    output.Append(c);
                    break;

                case ':':
                    if (!InString())
                    {
                        inVariableAssignment = true;
                        output.Append(Space);
                        output.Append(c);
                        output.Append(Space);
                    }
                    else
                        output.Append(c);

                    break;

                case '"':
                    if (!inSingleString && prevChar != '\\')
                        inDoubleString = !inDoubleString;

                    output.Append(c);
                    break;
                case ' ':
                    if (InString())
                        output.Append(c);
                    break;

                default:
                    output.Append(c);
                    break;
            }
            prevChar = c;
        }

        return output.ToString();
    }
}

श्रेय [मृत लिंक]


2

के रूप में benjymous उठाई बाहर है, तो आप उपयोग कर सकते हैं Newtonsoft.Json एक अस्थायी वस्तु और deserialize / serialize साथ।

var obj = JsonConvert.DeserializeObject(jsonString); 
var formatted = JsonConvert.SerializeObject(obj, Formatting.Indented);

1
@dvdmn allredy ने दो साल पहले उसी awser को पोस्ट किया था
NtFreX

2

सभी क्रेडिट फ्रैंक तज़बेटिस के हैं। हालाँकि यह सबसे छोटा प्रत्यक्ष उदाहरण है, जो खाली स्ट्रिंग या टूटे हुए मूल JSON स्ट्रिंग के मामले में भी जीवित रहता है:

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

    ...
    private static string Format(string jsonString)
    {
        try
        {
            return JToken.Parse(jsonString).ToString(Formatting.Indented);
        }
        catch
        {
            return jsonString;
        }
    }

2

यह प्रत्येक आइटम को एक नई लाइन पर रखेगा

VB.NET

mytext = responseFromServer.Replace("{", vbNewLine + "{")

सी#

mytext = responseFromServer.Replace("{", Environment.NewLine + "{");

1

यह स्वीकृत उत्तर का एक प्रकार है जिसका उपयोग करना मुझे अच्छा लगता है। टिप्पणी किए गए भागों के परिणामस्वरूप मैं एक अधिक पठनीय प्रारूप पर विचार करता हूं (आपको अंतर देखने के लिए आसन्न कोड पर टिप्पणी करने की आवश्यकता होगी):

public class JsonHelper
{
    private const int INDENT_SIZE = 4;

    public static string FormatJson(string str)
    {
        str = (str ?? "").Replace("{}", @"\{\}").Replace("[]", @"\[\]");

        var inserts = new List<int[]>();
        bool quoted = false, escape = false;
        int depth = 0/*-1*/;

        for (int i = 0, N = str.Length; i < N; i++)
        {
            var chr = str[i];

            if (!escape && !quoted)
                switch (chr)
                {
                    case '{':
                    case '[':
                        inserts.Add(new[] { i, +1, 0, INDENT_SIZE * ++depth });
                        //int n = (i == 0 || "{[,".Contains(str[i - 1])) ? 0 : -1;
                        //inserts.Add(new[] { i, n, INDENT_SIZE * ++depth * -n, INDENT_SIZE - 1 });
                        break;
                    case ',':
                        inserts.Add(new[] { i, +1, 0, INDENT_SIZE * depth });
                        //inserts.Add(new[] { i, -1, INDENT_SIZE * depth, INDENT_SIZE - 1 });
                        break;
                    case '}':
                    case ']':
                        inserts.Add(new[] { i, -1, INDENT_SIZE * --depth, 0 });
                        //inserts.Add(new[] { i, -1, INDENT_SIZE * depth--, 0 });
                        break;
                    case ':':
                        inserts.Add(new[] { i, 0, 1, 1 });
                        break;
                }

            quoted = (chr == '"') ? !quoted : quoted;
            escape = (chr == '\\') ? !escape : false;
        }

        if (inserts.Count > 0)
        {
            var sb = new System.Text.StringBuilder(str.Length * 2);

            int lastIndex = 0;
            foreach (var insert in inserts)
            {
                int index = insert[0], before = insert[2], after = insert[3];
                bool nlBefore = (insert[1] == -1), nlAfter = (insert[1] == +1);

                sb.Append(str.Substring(lastIndex, index - lastIndex));

                if (nlBefore) sb.AppendLine();
                if (before > 0) sb.Append(new String(' ', before));

                sb.Append(str[index]);

                if (nlAfter) sb.AppendLine();
                if (after > 0) sb.Append(new String(' ', after));

                lastIndex = index + 1;
            }

            str = sb.ToString();
        }

        return str.Replace(@"\{\}", "{}").Replace(@"\[\]", "[]");
    }
}

1

बस का उपयोग करें JsonDocumentऔर Utf8JsonWriterकिसी तीसरे पक्ष के पुस्तकालय की आवश्यकता नहीं है। jsonStringआवश्यकता के लिए deserialization के लिए कोई लक्ष्य वस्तु नहीं ।

using System.IO;
using System.Text;
using System.Text.Json;

// other code ...

public string Prettify(string jsonString)
{
    using var stream = new MemoryStream();
    var document = JsonDocument.Parse(jsonString);
    var writer = new Utf8JsonWriter(stream, new JsonWriterOptions { Indented = true });
    document.WriteTo(writer);
    writer.Flush();
    return Encoding.UTF8.GetString(stream.ToArray());
}

आपको क्या लगता JsonDocument.Parseहै? निश्चित रूप से कि यह deserializes?
मपेन

0

जे ब्रायन मूल्य, एक अच्छा उदाहरण है, लेकिन कमियां हैं

{\"response\":[123, 456, {\"name\":\"John\"}, {\"count\":3}]}

स्वरूपण के बाद

{
    "response" : [
        123,
         456,
         {
            "name" : "John"
        },
         {
            "count" : 3
        }
    ]
}

अनुचित पूर्वाग्रह :(


0

उदाहरण

    public static string JsonFormatter(string json)
    {
        StringBuilder builder = new StringBuilder();

        bool quotes = false;

        bool ignore = false;

        int offset = 0;

        int position = 0;

        if (string.IsNullOrEmpty(json))
        {
            return string.Empty;
        }

        json = json.Replace(Environment.NewLine, "").Replace("\t", "");

        foreach (char character in json)
        {
            switch (character)
            {
                case '"':
                    if (!ignore)
                    {
                        quotes = !quotes;
                    }
                    break;
                case '\'':
                    if (quotes)
                    {
                        ignore = !ignore;
                    }
                    break;
            }

            if (quotes)
            {
                builder.Append(character);
            }
            else
            {
                switch (character)
                {
                    case '{':
                    case '[':
                        builder.Append(character);
                        builder.Append(Environment.NewLine);
                        builder.Append(new string(' ', ++offset * 4));
                        break;
                    case '}':
                    case ']':
                        builder.Append(Environment.NewLine);
                        builder.Append(new string(' ', --offset * 4));
                        builder.Append(character);
                        break;
                    case ',':
                        builder.Append(character);
                        builder.Append(Environment.NewLine);
                        builder.Append(new string(' ', offset * 4));
                        break;
                    case ':':
                        builder.Append(character);
                        builder.Append(' ');
                        break;
                    default:
                        if (character != ' ')
                        {
                            builder.Append(character);
                        }
                        break;
                }

                position++;
            }
        }

        return builder.ToString().Trim();
    }

0

यह संस्करण JSON बनाता है जो अधिक कॉम्पैक्ट है और मेरी राय में अधिक पठनीय है क्योंकि आप एक समय में अधिक देख सकते हैं। यह सबसे गहरी परत इनलाइन को स्वरूपित करके या कॉम्पैक्ट सरणी संरचना की तरह करता है।

कोड की कोई निर्भरता नहीं है लेकिन अधिक जटिल है।

{ 
  "name":"Seller", 
  "schema":"dbo",
  "CaptionFields":["Caption","Id"],
  "fields":[ 
    {"name":"Id","type":"Integer","length":"10","autoincrement":true,"nullable":false}, 
    {"name":"FirstName","type":"Text","length":"50","autoincrement":false,"nullable":false}, 
    {"name":"LastName","type":"Text","length":"50","autoincrement":false,"nullable":false}, 
    {"name":"LotName","type":"Text","length":"50","autoincrement":false,"nullable":true}, 
    {"name":"LotDetailsURL","type":"Text","length":"255","autoincrement":false,"nullable":true} 
  ]
}

कोड इस प्रकार है

private class IndentJsonInfo
{
    public IndentJsonInfo(string prefix, char openingTag)
    {
        Prefix = prefix;
        OpeningTag = openingTag;
        Data = new List<string>();
    }
    public string Prefix;
    public char OpeningTag;
    public bool isOutputStarted;
    public List<string> Data;
}
internal static string IndentJSON(string jsonString, int startIndent = 0, int indentSpaces = 2)
{
    if (String.IsNullOrEmpty(jsonString))
        return jsonString;

    try
    {
        var jsonCache = new List<IndentJsonInfo>();
        IndentJsonInfo currentItem = null;

        var sbResult = new StringBuilder();

        int curIndex = 0;
        bool inQuotedText = false;

        var chunk = new StringBuilder();

        var saveChunk = new Action(() =>
        {
            if (chunk.Length == 0)
                return;
            if (currentItem == null)
                throw new Exception("Invalid JSON: No container.");
            currentItem.Data.Add(chunk.ToString());
            chunk = new StringBuilder();
        });

        while (curIndex < jsonString.Length)
        {
            var cChar = jsonString[curIndex];
            if (inQuotedText)
            {
                // Get the rest of quoted text.
                chunk.Append(cChar);

                // Determine if the quote is escaped.
                bool isEscaped = false;
                var excapeIndex = curIndex;
                while (excapeIndex > 0 && jsonString[--excapeIndex] == '\\') isEscaped = !isEscaped;

                if (cChar == '"' && !isEscaped)
                    inQuotedText = false;
            }
            else if (Char.IsWhiteSpace(cChar))
            {
                // Ignore all whitespace outside of quotes.
            }
            else
            {
                // Outside of Quotes.
                switch (cChar)
                {
                    case '"':
                        chunk.Append(cChar);
                        inQuotedText = true;
                        break;
                    case ',':
                        chunk.Append(cChar);
                        saveChunk();
                        break;
                    case '{':
                    case '[':
                        currentItem = new IndentJsonInfo(chunk.ToString(), cChar);
                        jsonCache.Add(currentItem);
                        chunk = new StringBuilder();
                        break;
                    case '}':
                    case ']':
                        saveChunk();
                        for (int i = 0; i < jsonCache.Count; i++)
                        {
                            var item = jsonCache[i];
                            var isLast = i == jsonCache.Count - 1;
                            if (!isLast)
                            {
                                if (!item.isOutputStarted)
                                {
                                    sbResult.AppendLine(
                                        "".PadLeft((startIndent + i) * indentSpaces) +
                                        item.Prefix + item.OpeningTag);
                                    item.isOutputStarted = true;
                                }
                                var newIndentString = "".PadLeft((startIndent + i + 1) * indentSpaces);
                                foreach (var listItem in item.Data)
                                {
                                    sbResult.AppendLine(newIndentString + listItem);
                                }
                                item.Data = new List<string>();
                            }
                            else // If Last
                            {
                                if (!(
                                    (item.OpeningTag == '{' && cChar == '}') ||
                                    (item.OpeningTag == '[' && cChar == ']')
                                   ))
                                {
                                    throw new Exception("Invalid JSON: Container Mismatch, Open '" + item.OpeningTag + "', Close '" + cChar + "'.");
                                }

                                string closing = null;
                                if (item.isOutputStarted)
                                {
                                    var newIndentString = "".PadLeft((startIndent + i + 1) * indentSpaces);
                                    foreach (var listItem in item.Data)
                                    {
                                        sbResult.AppendLine(newIndentString + listItem);
                                    }
                                    closing = cChar.ToString();
                                }
                                else
                                {
                                    closing =
                                        item.Prefix + item.OpeningTag +
                                        String.Join("", currentItem.Data.ToArray()) +
                                        cChar;
                                }

                                jsonCache.RemoveAt(i);
                                currentItem = (jsonCache.Count > 0) ? jsonCache[jsonCache.Count - 1] : null;
                                chunk.Append(closing);
                            }
                        }
                        break;
                    default:
                        chunk.Append(cChar);
                        break;
                }
            }
            curIndex++;
        }

        if (inQuotedText)
            throw new Exception("Invalid JSON: Incomplete Quote");
        else if (jsonCache.Count != 0)
            throw new Exception("Invalid JSON: Incomplete Structure");
        else
        {
            if (chunk.Length > 0)
                sbResult.AppendLine("".PadLeft(startIndent * indentSpaces) + chunk);
            var result = sbResult.ToString();
            return result;
        }
    }
    catch (Exception ex)
    {
        throw;  // Comment out to return unformatted text if the format failed.
        // Invalid JSON, skip the formatting.
        return jsonString;
    }
}

फ़ंक्शन आपको इंडेंटेशन के लिए एक प्रारंभिक बिंदु निर्दिष्ट करने की अनुमति देता है क्योंकि मैं इसे एक ऐसी प्रक्रिया के भाग के रूप में उपयोग करता हूं जो बहुत बड़ी JSON स्वरूपित बैकअप फ़ाइलों को असेंबल करता है।

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