Cách đảm bảo chuỗi đó là JSON hợp lệ khi sử dụng JSON.NET


147

Tôi có một chuỗi thô. Tôi chỉ muốn xác thực xem chuỗi có hợp lệ JSON hay không. Tôi đang sử dụng JSON.NET.

Câu trả lời:


207

Thông qua mã:

Đặt cược tốt nhất của bạn là sử dụng phân tích cú pháp bên trong a try-catchvà bắt ngoại lệ trong trường hợp phân tích cú pháp không thành công. (Tôi không biết về bất kỳ TryParsephương pháp nào ) .

(Sử dụng JSON.Net)

Cách đơn giản nhất sẽ là Parsesử dụng chuỗi JToken.Parsevà cũng để kiểm tra xem chuỗi bắt đầu bằng {hoặc [kết thúc bằng }hoặc ]tương ứng (được thêm từ câu trả lời này ) :

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

Lý do để thêm kiểm tra cho {hoặc [vv dựa trên thực tế là JToken.Parsesẽ phân tích các giá trị như "1234"hoặc "'a string'"như một mã thông báo hợp lệ. Tùy chọn khác có thể là sử dụng cả hai JObject.ParseJArray.Parsephân tích cú pháp và xem có ai trong số họ thành công không, nhưng tôi tin rằng việc kiểm tra {}[]sẽ dễ dàng hơn. (Cảm ơn @RhinoDevel đã chỉ ra)

Không có JSON.Net

Bạn có thể sử dụng không gian tên .Net framework 4.5 System.Json , như:

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

(Nhưng, bạn phải cài đặt System.Jsonthông qua trình quản lý gói Nuget bằng lệnh: PM> Install-Package System.Json -Version 4.0.20126.16343trên Bảng điều khiển quản lý gói) (lấy từ đây )

Cách phi mã:

Thông thường, khi có một chuỗi json nhỏ và bạn đang cố gắng tìm một lỗi trong chuỗi json, thì tôi cá nhân thích sử dụng các công cụ trực tuyến có sẵn. Những gì tôi thường làm là:


3
Làm thế nào có thể làm điều này trong thời gian chạy. Tôi không muốn sử dụng thử bắt cho mục đích xác thực
user960567

1
Bạn có thể tạo Lược đồ cho JSON của mình và sau đó xác minh theo lược đồ đó, xem: Json.NET 3.5 Beta 2 - Xác thực lược đồ JSON
Habib

1
Bất kỳ cách nào để làm điều đó mà không có một khối thử? Tôi không sử dụng các khối thử trừ khi tôi giao dịch với một ẩn số. Tôi đang tìm kiếm một cái gì đó như JsonConvert.TryDeserializeObject. Hoạt động khai thác thử chỉ là mã xấu đơn giản.
Jordan

1
Sử dụng JSON.Net: Điều này không ném ngoại lệ : JToken.Parse("1234")! Có thể là một ý tưởng tốt để kiểm tra đầu tiên, nếu chuỗi bắt đầu bằng [hoặc {. Một cách khác là sử dụng JObject.Parse()JArray.Parse().
RhinoDevel

1
JToken.Parse("{a:1}")không không ném ngoại lệ mặc dù đây là JSON không hợp lệ - anên được trích dẫn ( stackoverflow.com/q/949449/3116322 )
Ande

31

Sử dụng JContainer.Parse(str)phương pháp để kiểm tra xem str có phải là Json hợp lệ không. Nếu điều này ném ngoại lệ thì đó không phải là một Json hợp lệ.

JObject.Parse- Có thể được sử dụng để kiểm tra xem chuỗi có phải là đối tượng Json hợp lệ không
JArray.Parse- Có thể được sử dụng để kiểm tra xem chuỗi có phải là Mảng Json hợp lệ hay không
JContainer.Parse- Có thể được sử dụng để kiểm tra cả đối tượng Json & Array


17
Thay vì JContainer, việc sử dụng loại JToken sẽ hợp lệ hơn vì phương thức Parse () được khai báo ở cấp độ này
Denis The Menace

6
Tôi giả sử rằng bạn đang nói về JSON.Net: JContainer không hoạt động theo cách đó, vì nó sẽ không ném ngoại lệ trong tất cả các trường hợp mong muốn. Ví dụ : JContainer.Parse("1234");.
RhinoDevel

Câu trả lời sai, JContainer.Pude hoạt động trên mọi thứ
Bộ công cụ

19

Dựa trên câu trả lời của Habib, bạn có thể viết một phương pháp mở rộng:

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

Mà sau đó có thể được sử dụng như thế này:

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

1
JToken.Parse(s);trả lại truengay cả khiJToken.Parse(123);
Thực hiện Makeluv

2
Trả lại truecho điều này không hợp lệ JSON:{A:{"B": 1}}
Mehdi Dehghani

Phương pháp mở rộng tuyệt vời để có :) Mặc dù nó có thể được đặt tên tốt hơn là "IsValidJson".
Mladen B.

11

Chỉ cần thêm một cái gì đó vào câu trả lời của @ Habib, bạn cũng có thể kiểm tra xem JSON đã cho có thuộc loại hợp lệ không:

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

Tôi thấy rằng JToken.Pude phân tích cú pháp JSON không hợp lệ, chẳng hạn như sau:

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

Dán chuỗi JSON vào http://jsonlint.com/ - không hợp lệ.

Vì vậy, tôi sử dụng:

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

Đó không phải là một chuỗi JSON không hợp lệ ecma-i Intl.org/publications/files/ECMA-ST/ECMA-404.pdf ở đây là tài liệu của ECMA tiêu chuẩn JSON và theo Giá trị JSON của Điểm 5 bạn có thể thấy giá trị có thể lấy giá trị null . Vì vậy, nó chỉ là một lỗi trong trình thông dịch jsonlint
Dominik Lemberger

4
Dominik, một giá trị JSON theo đọc của tôi về thông số bạn đã liên kết phải có một số mã thông báo hợp lệ, với văn bản null bằng chữ đại diện cho một giá trị null. Các giá trị hợp lệ là "một đối tượng, mảng, số, chuỗi, true, false hoặc null" theo thông số bạn đã tham chiếu. AFAICS không có giá trị hợp lệ không có mã thông báo giá trị.
Kirtlander

Điều này có vẻ ổn với JSON không hợp lệ trông như thế này{ name : "l am invalid JSON" }
Jon49

2

Option Tùy chọn thay thế Không sử dụng JSON.Net

Đối với .Net Core / .Net 5 ( trong bản xem trước khi viết bài này ), người ta cũng có thể sử dụng System.Text.Jsonkhông gian tên và phân tích cú pháp bằng cách sử dụng JsonDocument. Ví dụ là một phương thức mở rộng dựa trên các hoạt động không gian tên:

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

    return false;
}

1

Về câu trả lời của Tom Beech; Tôi đã đưa ra những điều sau đây:

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

Với cách sử dụng như sau:

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

3
Đây không phải là tiểu thuyết - bạn đã thực hiện một phương thức mở rộng không phải là một phương thức mở rộng. Câu trả lời của Tom Beech đã có thể đạt được những gì bạn cần (Nói chung, tôi cũng sẽ cau mày khi thêm các phương thức mở rộng loại này vào string, nhưng câu trả lời này thực sự không nên ở đây hoặc b) nói "Tôi đã sử dụng câu trả lời của Tom Beech " mà không các this, tức là không làm cho nó trở thành một thành viên mở rộng) - cả hai câu trả lời này và tham khảo một có ngắn gọn và điểm yếu giống hệt nhau. Nếu bạn phải đưa ra quan điểm này, chỉ cần đưa ra nhận xét về câu trả lời khác.
Ruben Bartelink

1

JToken.Typecó sẵn sau khi phân tích thành công. Điều này có thể được sử dụng để loại bỏ một số lời mở đầu trong các câu trả lời ở trên và cung cấp cái nhìn sâu sắc để kiểm soát kết quả tốt hơn. Đầu vào hoàn toàn không hợp lệ (ví dụ, "{----}".IsValidJson();vẫn sẽ đưa ra một ngoại lệ).

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

Tham khảo Json.Net cho JToken.Type: https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Linq_JTokenType.htmlm


0

Phương pháp này không yêu cầu thư viện bên ngoài

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

Đây là một phương pháp mở rộng TryPude dựa trên câu trả lời của 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;
    }
}

Sử dụng:

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

0

Tôi đang sử dụng cái này:

  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;
     }
  }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.