So stellen Sie mithilfe von JSON.NET sicher, dass die Zeichenfolge JSON gültig ist

147

Ich habe eine rohe Schnur. Ich möchte nur überprüfen, ob die Zeichenfolge JSON gültig ist oder nicht. Ich benutze JSON.NET.

user960567
quelle

Antworten:

207

Durch Code:

Am besten verwenden Sie parse in a try-catchund fangen bei fehlgeschlagener Analyse eine Ausnahme ab. (Mir ist keine TryParseMethode bekannt) .

(Verwenden von JSON.Net)

Einfachste Weg , um würde Parsedie Zeichenfolge mit JToken.Parse, und auch zu überprüfen , ob die Zeichenfolge beginnt mit {oder [und endet mit }oder ]jeweils (von dieser aufgenommener Antwort ) :

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

Der Grund für das Hinzufügen von Überprüfungen für {oder [usw. beruhte auf der Tatsache, dass JToken.Parsedie Werte wie "1234"oder "'a string'"als gültiges Token analysiert wurden . Die andere Möglichkeit könnte darin bestehen, beide JObject.Parseund das JArray.ParseParsen zu verwenden und zu prüfen, ob einer von ihnen erfolgreich ist, aber ich glaube, dass es einfacher ist , dies zu überprüfen {}und []sollte es auch sein. (Danke @RhinoDevel für den Hinweis )

Ohne JSON.Net

Sie können den .NET Framework 4.5 System.Json-Namespace wie folgt verwenden :

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

(Sie müssen jedoch System.Jsonüber den Nuget-Paketmanager mit dem folgenden Befehl installieren : PM> Install-Package System.Json -Version 4.0.20126.16343on Package Manager Console) (von hier übernommen )

Non-Code-Weg:

Wenn es eine kleine JSON-Zeichenfolge gibt und Sie versuchen, einen Fehler in der JSON-Zeichenfolge zu finden, bevorzuge ich persönlich die Verwendung verfügbarer Online-Tools. Was ich normalerweise mache ist:

Habib
quelle
3
Wie kann das zur Laufzeit gemacht werden? Ich möchte try catch nicht zu Validierungszwecken verwenden
user960567
1
Sie können ein Schema für Ihren JSON erstellen und später anhand
Habib
1
Wie geht das ohne Try-Block? Ich verwende keine Try-Blöcke, es sei denn, ich habe es mit einem Unbekannten zu tun. Ich suche etwas wie JsonConvert.TryDeserializeObject. Operative Try-Catches sind einfach nur schlechter Code.
Jordanien
1
Verwenden von JSON.Net: Dies löst keine Ausnahme aus : JToken.Parse("1234")! Es könnte eine gute Idee sein, zuerst zu überprüfen, ob die Zeichenfolge mit [oder beginnt {. Eine andere Alternative ist Verwendung JObject.Parse()und JArray.Parse().
RhinoDevel
1
JToken.Parse("{a:1}")löst keine Ausnahme aus, obwohl dies ungültig ist JSON - asollte zitiert werden ( stackoverflow.com/q/949449/3116322 )
Ande
31

Verwenden Sie die JContainer.Parse(str)Methode, um zu überprüfen, ob der str ein gültiger Json ist. Wenn dies eine Ausnahme auslöst, handelt es sich nicht um einen gültigen Json.

JObject.Parse- Kann verwendet werden, um zu überprüfen, ob die Zeichenfolge ein gültiges Json-Objekt ist.
JArray.Parse- Kann verwendet werden, um zu überprüfen, ob die Zeichenfolge ein gültiges Json-Array ist.
JContainer.Parse- Kann verwendet werden, um sowohl nach Json-Objekt als auch nach Array zu suchen

Senthilkumar Viswanathan
quelle
17
Anstelle von JContainer ist es gültiger, den Typ JToken zu verwenden, da die Parse () -Methode auf dieser Ebene deklariert ist
Denis The Menace
6
Ich gehe davon aus, dass Sie über JSON.Net sprechen: JContainer funktioniert nicht so, weil es nicht in allen gewünschten Fällen eine Ausnahme auslöst . Beispiel : JContainer.Parse("1234");.
RhinoDevel
Falsche Antwort, JContainer.Parse funktioniert an allem
Toolkit
19

Aufbauend auf Habibs Antwort könnten Sie eine Erweiterungsmethode schreiben:

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

Welches kann dann so verwendet werden:

if(stringObject.ValidateJSON())
{
    // Valid JSON!
}
Tom Beech
quelle
1
JToken.Parse(s);kehrt zurück, trueauch wennJToken.Parse(123);
Makeluv
2
Rückkehr truefür diesen ungültigen JSON:{A:{"B": 1}}
Mehdi Dehghani
Schöne Erweiterungsmethode zu haben :) Obwohl es wahrscheinlich besser als "IsValidJson" benannt wäre.
Mladen B.
11

Um der Antwort von @ Habib etwas hinzuzufügen, können Sie auch überprüfen, ob JSON von einem gültigen Typ stammt:

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

Ich habe festgestellt, dass JToken.Parse ungültiges JSON wie das folgende falsch analysiert:

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

Fügen Sie die JSON-Zeichenfolge in http://jsonlint.com/ ein - sie ist ungültig.

Also benutze ich:

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;
}
Andrew Roberts
quelle
Dies ist keine ungültige JSON- Zeichenfolge. Ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf Hier ist die Dokumentation des JSON-Standard-ECMA. Unter Punkt 5 JSON-Werte können Sie sehen, dass ein Wert null als Wert annehmen kann . Es ist also nur ein Fehler im jsonlint-Interpreter
Dominik Lemberger
4
Dominik, ein JSON-Wert gemäß meiner Lektüre der von Ihnen verknüpften Spezifikation muss ein gültiges Token haben, wobei der wörtliche Nulltext einen Nullwert darstellt. Gültige Werte sind "ein Objekt, ein Array, eine Zahl, eine Zeichenfolge, wahr, falsch oder null" gemäß der von Ihnen angegebenen Spezifikation. AFAICS gibt es keinen gültigen Wert ohne Werttoken.
Kirtlander
Dies sieht so aus, als wäre es in Ordnung mit ungültigem JSON, das so aussieht{ name : "l am invalid JSON" }
Jon49
2

⚠️ Alternative Option ohne JSON.Net ⚠️

Für .Net Core / .Net 5 ( in der Vorschau zum jetzigen Zeitpunkt ) kann man auch den System.Text.JsonNamespace verwenden und mit dem analysieren JsonDocument. Beispiel ist eine Erweiterungsmethode, die auf den Namespace-Operationen basiert:

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

    return false;
}
ΩmegaMan
quelle
1

In Bezug auf die Antwort von Tom Beech; Ich habe mir stattdessen Folgendes ausgedacht:

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

Mit einer Verwendung der folgenden:

if (ValidateJSON(strMsg))
{
    var newGroup = DeserializeGroup(strMsg);
}
HappyCoding
quelle
3
Dies ist nicht neu - Sie haben eine Erweiterungsmethode nicht zu einer Erweiterungsmethode gemacht. Die Antwort von Tom Beech kann bereits das erreichen, was Sie brauchen (im Allgemeinen würde ich auch das Hinzufügen von Erweiterungsmethoden dieser Art missbilligen string, aber diese Antwort sollte wirklich entweder a) nicht hier sein oder b) sagen "Ich habe die Antwort von Tom Beech verwendet " ohne die this, dh ohne es zu einem Erweiterungsmitglied zu machen) - sowohl diese Antwort als auch die referenzierte haben identische Kürze und Schwächen. Wenn Sie darauf hinweisen müssen, kommentieren Sie einfach die andere Antwort.
Ruben Bartelink
1

JToken.Typeist nach erfolgreicher Analyse verfügbar. Dies kann verwendet werden, um einen Teil der Präambel in den obigen Antworten zu entfernen und Einblicke für eine genauere Kontrolle des Ergebnisses zu erhalten. Völlig ungültige Eingabe (z. B. "{----}".IsValidJson();wird immer noch eine Ausnahme ausgelöst ).

    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-Referenz für JToken.Type: https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Linq_JTokenType.htm

Randy Larson
quelle
0

Diese Methode erfordert keine externen Bibliotheken

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

Hier ist eine TryParse-Erweiterungsmethode, die auf Habibs Antwort basiert:

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

Verwendung:

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

Ich benutze dieses:

  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;
     }
  }
Yousha Aleayoub
quelle