Come assicurarsi che la stringa sia JSON valida utilizzando JSON.NET


147

Ho una stringa grezza. Voglio solo confermare se la stringa è valida o meno JSON. Sto usando JSON.NET.

Risposte:


207

Tramite codice:

La soluzione migliore è utilizzare l'analisi all'interno di a try-catche rilevare l'eccezione in caso di analisi non riuscita. (Non sono a conoscenza di alcun TryParsemetodo) .

(Utilizzando JSON.Net)

Il modo più semplice sarebbe quello di Parseutilizzare la stringa JToken.Parsee anche di verificare se la stringa inizia con {o [e termina con }o ]rispettivamente (aggiunto da questa risposta ) :

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

Il motivo per aggiungere controlli per {o [ecc. Era basato sul fatto che JToken.Parseavrebbe analizzato i valori come "1234"o "'a string'"come token valido. L'altra opzione potrebbe essere quella di utilizzare entrambi JObject.Parsee JArray.Parsenell'analisi e vedere se qualcuno di loro ha esito positivo, ma credo che il controllo {}e []dovrebbe essere più semplice. (Grazie @RhinoDevel per indicare fuori)

Senza JSON.Net

È possibile utilizzare lo spazio dei nomi System.Json di .Net framework 4.5 , come:

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

(Ma devi installare System.Jsontramite Nuget Package Manager usando il comando: PM> Install-Package System.Json -Version 4.0.20126.16343su Package Manager Console) (preso da qui )

Modo senza codice:

Di solito, quando c'è una piccola stringa JSON e stai cercando di trovare un errore nella stringa JSON, preferisco personalmente utilizzare gli strumenti online disponibili. Quello che faccio di solito è:


3
Come può farlo in fase di esecuzione. Non voglio usare try catch a scopo di validazione
user960567,

1
È possibile creare uno schema per il proprio JSON e successivamente verificarlo rispetto a quello schema, consultare: Json.NET 3.5 Beta 2 - Convalida dello schema JSON
Habib

1
Un modo per farlo senza un blocco try? Non uso i blocchi di prova a meno che non abbia a che fare con uno sconosciuto. Sto cercando qualcosa come JsonConvert. TryDeserializeObject. Le catture di prova operative sono semplicemente codice errato.
Giordania,

1
Utilizzando JSON.Net: Ciò non un'eccezione: JToken.Parse("1234")! Potrebbe essere una buona idea controllare prima, se la stringa inizia con [o {. Un'altra alternativa è l'uso JObject.Parse()e JArray.Parse().
RhinoDevel,

1
JToken.Parse("{a:1}")non senza lanciare un'eccezione, anche se questo è JSON valido - adovrà essere espresso ( stackoverflow.com/q/949449/3116322 )
Ande

31

Utilizzare il JContainer.Parse(str)metodo per verificare se str è un Json valido. Se questo genera un'eccezione, non è un Json valido.

JObject.Parse- Può essere usato per verificare se la stringa è un oggetto Json valido
JArray.Parse- Può essere usato per controllare se la stringa è un array Json valido
JContainer.Parse- Può essere usato per controllare sia l'oggetto Json sia l'array


17
Invece di JContainer è più valido usare il tipo JToken poiché il metodo Parse () è dichiarato a questo livello
Denis The Menace

6
Presumo che tu stia parlando di JSON.Net: JContainer non funziona in questo modo, perché non genererà un'eccezione in tutti i casi desiderati. Esempio: JContainer.Parse("1234");.
RhinoDevel,

Risposta errata, JContainer.Parse funziona su qualsiasi cosa
Toolkit

19

Sulla base della risposta di Habib, è possibile scrivere un metodo di estensione:

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

Che può quindi essere utilizzato in questo modo:

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

1
JToken.Parse(s);ritorna trueanche seJToken.Parse(123);
Make Makeluv

2
Ritorno trueper questo invalido JSON:{A:{"B": 1}}
Mehdi Dehghani,

Metodo di estensione piacevole da avere :) Anche se probabilmente sarebbe meglio chiamarlo "IsValidJson".
Mladen B.

11

Solo per aggiungere qualcosa alla risposta di @ Habib, puoi anche verificare se un dato JSON proviene da un tipo valido:

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

Ho scoperto che JToken.Parse analizza erroneamente JSON non valido come il seguente:

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

Incolla la stringa JSON in http://jsonlint.com/ - non è valida.

Quindi io uso:

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

Questa non è una stringa JSON non valida ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf qui è la documentazione dell'ECMA standard JSON e sotto il punto 5 Valori JSON puoi vedere che un valore può prendere null come valore . Quindi è solo un bug nell'interprete jsonlint
Dominik Lemberger il

4
Dominik, un valore JSON secondo la mia lettura delle specifiche che hai collegato deve avere un token valido, con il testo null letterale che rappresenta un valore null. I valori validi sono "un oggetto, un array, un numero, una stringa, vero, falso o nullo" in base alla specifica a cui si fa riferimento. AFAICS non esiste un valore valido senza token valore.
Kirtlander,

Sembra che andrà bene con JSON non valido che assomiglia a questo{ name : "l am invalid JSON" }
Jon49

2

⚠️ Opzione alternativa che non utilizza JSON.Net ⚠️

Per .Net Core / .Net 5 ( in anteprima al momento della stesura di questo documento ) si può anche usare lo System.Text.Jsonspazio dei nomi e analizzare usando il JsonDocument. Esempio è un metodo di estensione basato sulle operazioni dello spazio dei nomi:

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

    return false;
}

1

Per quanto riguarda la risposta di Tom Beech; Invece ho pensato a quanto segue:

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

Con un utilizzo di quanto segue:

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

3
Questo non è un romanzo: hai reso un metodo di estensione non un metodo di estensione. La risposta di Tom Beech può già raggiungere ciò di cui hai bisogno (in generale, mi accorgerei anche di aggiungere metodi di estensione di questo tipo string, ma questa risposta dovrebbe o a) non essere qui oppure b) dire "Ho usato la risposta di Tom Beech " senza il this, cioè senza renderlo un membro di estensione) - sia questa risposta che quella referenziata hanno identica brevità e punti deboli. Se devi fare questo punto, inserisci un commento sull'altra risposta.
Ruben Bartelink il

1

JToken.Typeè disponibile dopo un'analisi riuscita. Questo può essere usato per eliminare parte del preambolo nelle risposte sopra e fornire informazioni per un controllo più preciso del risultato. Immissione totalmente non valida (ad es. "{----}".IsValidJson();Genererà comunque un'eccezione).

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

Riferimento Json.Net per JToken.Type: https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Linq_JTokenType.htm


0

Questo metodo non richiede librerie esterne

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

Ecco un metodo di estensione TryParse basato sulla risposta di 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;
    }
}

Uso:

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

0

Sto usando questo:

  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;
     }
  }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.