วิธีการตรวจสอบให้แน่ใจว่าสตริงนั้นเป็น JSON ที่ถูกต้องโดยใช้ JSON.NET


147

ฉันมีสตริงดิบ ฉันแค่ต้องการตรวจสอบว่าสตริงเป็น JSON ที่ถูกต้องหรือไม่ ฉันกำลังใช้ JSON.NET

คำตอบ:


207

ผ่านรหัส:

ทางออกที่ดีที่สุดของคุณคือการใช้การแยกวิเคราะห์ภายในtry-catchและจับยกเว้นในกรณีที่การแยกวิเคราะห์ล้มเหลว (ผมไม่ได้ตระหนักถึงการใดTryParseวิธีการ)

(ใช้ JSON.Net)

วิธีที่ง่ายที่สุดคือParseการใช้สตริงJToken.Parseและเพื่อตรวจสอบว่าสตริงเริ่มต้นด้วย{หรือ[และลงท้ายด้วย}หรือ]ตามลำดับ(เพิ่มจากคำตอบนี้) :

private static bool IsValidJson(string strInput)
{
    if (string.IsNullOrWhiteSpace(stringValue)) { return false;}
    strInput = strInput.Trim();
    if ((strInput.StartsWith("{") && strInput.EndsWith("}")) || //For object
        (strInput.StartsWith("[") && strInput.EndsWith("]"))) //For array
    {
        try
        {
            var obj = JToken.Parse(strInput);
            return true;
        }
        catch (JsonReaderException jex)
        {
            //Exception in parsing json
            Console.WriteLine(jex.Message);
            return false;
        }
        catch (Exception ex) //some other exception
        {
            Console.WriteLine(ex.ToString());
            return false;
        }
    }
    else
    {
        return false;
    }
}

เหตุผลในการเพิ่มการตรวจสอบสำหรับ{หรือ[อื่น ๆ นั้นขึ้นอยู่กับข้อเท็จจริงที่JToken.Parseจะแยกค่าเช่น"1234"หรือ"'a string'"เป็นโทเค็นที่ถูกต้อง ตัวเลือกอื่น ๆ อาจจะใช้ทั้งสองJObject.ParseและJArray.Parseในการแยกวิเคราะห์และดูว่าคนของพวกเขาประสบความสำเร็จ แต่ผมเชื่อว่าการตรวจสอบ{}และ[]ควรจะง่าย (ขอบคุณ @RhinoDevel สำหรับการชี้ให้เห็น)

ไม่มี JSON.Net

คุณสามารถใช้. Net framework 4.5 System.Json namespaceเช่น:

string jsonString = "someString";
try
{
    var tmpObj = JsonValue.Parse(jsonString);
}
catch (FormatException fex)
{
    //Invalid json format
    Console.WriteLine(fex);
}
catch (Exception ex) //some other exception
{
    Console.WriteLine(ex.ToString());
}

(แต่คุณต้องติดตั้งSystem.Jsonผ่านผู้จัดการแพคเกจ Nuget โดยใช้คำสั่ง: PM> Install-Package System.Json -Version 4.0.20126.16343บนคอนโซลตัวจัดการแพคเกจ) (นำมาจากที่นี่ )

วิธีที่ไม่ใช่รหัส:

โดยปกติเมื่อมีสตริง json ขนาดเล็กและคุณพยายามที่จะหาข้อผิดพลาดในสตริง json แล้วฉันเองชอบที่จะใช้เครื่องมือออนไลน์ที่มีอยู่ สิ่งที่ฉันมักจะทำคือ:

  • วางสตริง JSON ในJSONLint JSON Validatorและดูว่าเป็น JSON ที่ถูกต้องหรือไม่
  • ต่อมาคัดลอก JSON ที่ถูกต้องไปที่http://json2csharp.com/และสร้างคลาสเทมเพลตสำหรับมันแล้วยกเลิกการทำให้เป็นอันดับโดยใช้ JSON.Net

3
จะทำสิ่งนี้ได้อย่างไรที่รันไทม์ ฉันไม่ต้องการใช้ลองจับเพื่อวัตถุประสงค์ในการตรวจสอบ
user960567

1
คุณสามารถสร้าง Schema สำหรับ JSON ของคุณและตรวจสอบกับ schema นั้นในภายหลัง: Json.NET 3.5 Beta 2 - การตรวจสอบ schema JSON
Habib

1
วิธีใดที่จะทำได้โดยไม่ต้องลองบล็อก? ฉันไม่ได้ใช้บล็อกลองใช้ยกเว้นว่าฉันไม่รู้จัก ฉันกำลังมองหาบางอย่างเช่น JsonConvert.TryDeserializeObject การลองใช้งานเป็นเพียงโค้ดไม่ดี
Jordan

1
ใช้ JSON.Net:นี้ไม่ได้โยนข้อยกเว้น: JToken.Parse("1234")! อาจเป็นความคิดที่ดีที่จะตรวจสอบก่อนถ้าสตริงเริ่มต้นด้วยหรือ[ {อีกทางเลือกหนึ่งคือการใช้และJObject.Parse() JArray.Parse()
RhinoDevel

1
JToken.Parse("{a:1}")ไม่ได้โยนข้อยกเว้นแม้ว่านี้เป็น JSON ที่ไม่ถูกต้อง - aควรจะยกมา ( stackoverflow.com/q/949449/3116322 )
Ande

31

ใช้JContainer.Parse(str)วิธีการตรวจสอบว่า str เป็น Json ที่ถูกต้อง หากสิ่งนี้มีข้อยกเว้นแสดงว่าไม่ใช่ Json ที่ถูกต้อง

JObject.Parse- สามารถใช้เพื่อตรวจสอบว่าสตริงเป็นวัตถุ Json ที่ถูกต้อง
JArray.Parse- สามารถใช้เพื่อตรวจสอบว่าสตริงนั้นเป็น Json Array ที่ถูกต้องหรือ
JContainer.Parseไม่ - สามารถใช้เพื่อตรวจสอบทั้งวัตถุ Json และ Array


17
แทนที่จะเป็น JContainer การใช้ type JToken นั้นถูกต้องมากกว่าเนื่องจากวิธี Parse () ถูกประกาศในระดับนี้
Denis The Menace

6
ฉันสมมติว่าคุณกำลังพูดถึง JSON.Net: JContainer ไม่ทำงานเช่นนั้นเพราะจะไม่ส่งข้อยกเว้นในทุกกรณีที่ต้องการ ตัวอย่าง: JContainer.Parse("1234");.
RhinoDevel

คำตอบที่ไม่ถูกต้อง JContainer.Parse ทำงานได้ทุกอย่าง
Toolkit

19

จากคำตอบของ Habib คุณสามารถเขียนวิธีการขยายได้:

public static bool ValidateJSON(this string s)
{
    try
    {
        JToken.Parse(s);
        return true;
    }
    catch (JsonReaderException ex)
    {
        Trace.WriteLine(ex);
        return false;
    }
}

ซึ่งสามารถใช้ดังนี้:

if(stringObject.ValidateJSON())
{
    // Valid JSON!
}

1
JToken.Parse(s);ส่งคืนtrueแม้ว่าJToken.Parse(123);
ทำให้ Makeluv

2
ส่งคืนtrueสำหรับสิ่งที่ไม่ถูกต้องนี้JSON:{A:{"B": 1}}
Mehdi Dehghani

วิธีการขยายที่ดีที่จะมี :) แม้ว่ามันอาจจะมีชื่อที่ดีกว่าว่า "IsValidJson"
Mladen B.

11

เพียงเพิ่มบางสิ่งในคำตอบของ @ Habib คุณสามารถตรวจสอบว่า JSON ที่กำหนดนั้นมาจากประเภทที่ถูกต้อง:

public static bool IsValidJson<T>(this string strInput)
{
    strInput = strInput.Trim();
    if ((strInput.StartsWith("{") && strInput.EndsWith("}")) || //For object
        (strInput.StartsWith("[") && strInput.EndsWith("]"))) //For array
    {
        try
        {
            var obj = JsonConvert.DeserializeObject<T>(strInput);
            return true;
        }
        catch // not valid
        {             
            return false;
        }
    }
    else
    {
        return false;
    }
}

7

ฉันพบว่า JToken.Parse แยกวิเคราะห์ JSON ที่ไม่ถูกต้องเช่นดังต่อไปนี้:

{
"Id" : , 
"Status" : 2
}

วางสตริง JSON ลงในhttp://jsonlint.com/ - มันไม่ถูกต้อง

ดังนั้นฉันใช้:

public static bool IsValidJson(this string input)
{
    input = input.Trim();
    if ((input.StartsWith("{") && input.EndsWith("}")) || //For object
        (input.StartsWith("[") && input.EndsWith("]"))) //For array
    {
        try
        {
            //parse the input into a JObject
            var jObject = JObject.Parse(input);

            foreach(var jo in jObject)
            {
                string name = jo.Key;
                JToken value = jo.Value;

                //if the element has a missing value, it will be Undefined - this is invalid
                if (value.Type == JTokenType.Undefined)
                {
                    return false;
                }
            }
        }
        catch (JsonReaderException jex)
        {
            //Exception in parsing json
            Console.WriteLine(jex.Message);
            return false;
        }
        catch (Exception ex) //some other exception
        {
            Console.WriteLine(ex.ToString());
            return false;
        }
    }
    else
    {
        return false;
    }

    return true;
}

นั่นไม่ใช่ JSON String ที่ไม่ถูกต้องecma-international.org/publications/files/ECMA-ST/ECMA-404.pdfนี่คือเอกสารของมาตรฐาน JSON ECMA และภายใต้ค่า JSON มาตรฐานของจุดที่ 5 คุณสามารถเห็นค่าที่สามารถใช้เป็นค่าว่าง . ดังนั้นมันจึงเป็นข้อผิดพลาดในล่าม jsonlint
Dominik Lemberger

4
Dominik, ค่า JSON ตามการอ่านข้อมูลจำเพาะที่คุณเชื่อมโยงของฉันจะต้องมีโทเค็นที่ถูกต้องบางส่วน, ด้วยข้อความ null ตัวอักษรที่แทนค่า null ค่าที่ถูกต้องคือ "วัตถุ, อาร์เรย์, จำนวน, สตริง, จริง, เท็จหรือ null" ตามข้อมูลจำเพาะที่คุณอ้างอิง AFAICS ไม่มีค่าที่ถูกต้องโดยไม่มีโทเค็นค่า
Kirtlander

ดูเหมือนว่าจะไม่เป็นไรด้วย JSON ที่ไม่ถูกต้องซึ่งมีลักษณะเช่นนี้{ name : "l am invalid JSON" }
Jon49

2

Option ตัวเลือกสำรองที่ไม่ได้ใช้ JSON.Net ⚠️

สำหรับ NET core / สุทธิ 5 ( ในการแสดงตัวอย่างเช่นการเขียนนี้ ) หนึ่งยังสามารถใช้System.Text.Jsonnamespace JsonDocumentและแยกใช้ ตัวอย่างเป็นวิธีการขยายตามการดำเนินงานของ namespace:

public static bool IsJsonValid(this string txt)
{
    try { return JsonDocument.Parse(txt) != null; } catch {}

    return false;
}

1

เกี่ยวกับคำตอบของทอมบีช ฉันมากับสิ่งต่อไปนี้แทน:

public bool ValidateJSON(string s)
{
    try
    {
        JToken.Parse(s);
        return true;
    }
    catch (JsonReaderException ex)
    {
        Trace.WriteLine(ex);
        return false;
    }
}

ด้วยการใช้งานดังต่อไปนี้:

if (ValidateJSON(strMsg))
{
    var newGroup = DeserializeGroup(strMsg);
}

3
นี่ไม่ใช่เรื่องแปลกใหม่ - คุณสร้างวิธีส่วนขยายไม่ใช่วิธีส่วนขยาย คำตอบของ Tom Beech นั้นสามารถบรรลุสิ่งที่คุณต้องการได้ (โดยทั่วไปแล้วฉันยังขมวดคิ้วในการเพิ่มวิธีการขยายประเภทstringนี้ แต่คำตอบนี้ควรจะเป็น) ไม่อยู่ที่นี่หรือ b) พูดว่า "ฉันใช้คำตอบของ Tom Beech " โดยไม่ต้องthisคือโดยไม่ต้องทำให้สมาชิกส่วนขยาย) - ทั้งคำตอบนี้และอ้างถึงหนึ่งมีความกะทัดรัดและจุดอ่อนเหมือนกัน หากคุณต้องทำให้ประเด็นนี้เพียงแค่ใส่ความเห็นในคำตอบอื่น ๆ
Ruben Bartelink

1

JToken.Typeสามารถใช้ได้หลังจากการแยกวิเคราะห์ที่ประสบความสำเร็จ สิ่งนี้สามารถใช้เพื่อกำจัดคำนำบางส่วนในคำตอบข้างต้นและให้ข้อมูลเชิงลึกสำหรับการควบคุมผลลัพธ์อย่างละเอียดยิ่งขึ้น อินพุตที่ไม่ถูกต้องทั้งหมด (เช่น"{----}".IsValidJson();จะยังคงมีข้อยกเว้น)

    public static bool IsValidJson(this string src)
    {
        try
        {
            var asToken = JToken.Parse(src);
            return asToken.Type == JTokenType.Object || asToken.Type == JTokenType.Array;
        }
        catch (Exception)  // Typically a JsonReaderException exception if you want to specify.
        {
            return false;
        }
    }

การอ้างอิง Json.Net สำหรับJToken.Type: https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Linq_JTokenType.htm


0

วิธีนี้ไม่ต้องการไลบรารีภายนอก

using System.Web.Script.Serialization;
bool IsValidJson(string json)
    {
        try {
            var serializer = new JavaScriptSerializer();
            dynamic result = serializer.DeserializeObject(json);
            return true;
        } catch { return false; }
    }

0

นี่คือวิธีการขยาย TryParse ตามคำตอบของ Habib:

public static bool TryParse(this string strInput, out JToken output)
{
    if (String.IsNullOrWhiteSpace(strInput))
    {
        output = null;
        return false;
    }
    strInput = strInput.Trim();
    if ((strInput.StartsWith("{") && strInput.EndsWith("}")) || //For object
        (strInput.StartsWith("[") && strInput.EndsWith("]"))) //For array
    {
        try
        {
            output = JToken.Parse(strInput);
            return true;
        }
        catch (JsonReaderException jex)
        {
            //Exception in parsing json
            //optional: LogError(jex);
            output = null;
            return false;
        }
        catch (Exception ex) //some other exception
        {
            //optional: LogError(ex);
            output = null;
            return false;
        }
    }
    else
    {
        output = null;
        return false;
    }
}

การใช้งาน:

JToken jToken;
if (strJson.TryParse(out jToken))
{
    // work with jToken
}
else
{
    // not valid json
}

0

ฉันใช้อันนี้:

  internal static bool IsValidJson(string data)
  {
     data = data.Trim();
     try
     {
        if (data.StartsWith("{") && data.EndsWith("}"))
        {
           JToken.Parse(data);
        }
        else if (data.StartsWith("[") && data.EndsWith("]"))
        {
           JArray.Parse(data);
        }
        else
        {
           return false;
        }
        return true;
     }
     catch
     {
        return false;
     }
  }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.