Comment s'assurer que cette chaîne est JSON valide à l'aide de JSON.NET

147

J'ai une corde brute. Je veux juste valider si la chaîne est JSON valide ou non. J'utilise JSON.NET.

user960567
la source

Réponses:

207

Par code:

Votre meilleur pari est d'utiliser parse dans une try-catchexception et catch en cas d'échec de l'analyse. (Je ne connais aucune TryParseméthode) .

(Utilisation de JSON.Net)

Le moyen le plus simple serait d'utiliser Parsela chaîne JToken.Parse, et également de vérifier si la chaîne commence par {ou [et se termine par }ou ]respectivement (ajouté à partir de cette réponse ) :

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

La raison pour laquelle ajouter des vérifications pour {ou [etc était basée sur le fait que JToken.Parsel'analyse des valeurs telles que "1234"ou "'a string'"comme un jeton valide. L'autre option pourrait être d'utiliser à la fois JObject.Parseet JArray.Parsedans l' analyse syntaxique et voir si quelqu'un d'entre eux réussit, mais je crois que la vérification des {}et []devrait être plus facile. (Merci @RhinoDevel de l'avoir signalé )

Sans JSON.Net

Vous pouvez utiliser l' espace de noms .Net Framework 4.5 System.Json , comme:

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

(Mais, vous devez installer System.Jsonvia le gestionnaire de packages Nuget en utilisant la commande: PM> Install-Package System.Json -Version 4.0.20126.16343sur la console du gestionnaire de packages) (pris à partir d' ici )

Manière non-code:

Habituellement, quand il y a une petite chaîne json et que vous essayez de trouver une erreur dans la chaîne json, je préfère personnellement utiliser les outils en ligne disponibles. Ce que je fais habituellement, c'est:

  • Coller la chaîne JSON dans JSONLint Le validateur JSON et voir si c'est un JSON valide.
  • Copiez ultérieurement le JSON correct sur http://json2csharp.com/ et générez une classe de modèle pour celui-ci, puis dé-sérialisez-le à l'aide de JSON.Net.
Habib
la source
3
Comment faire cela au moment de l'exécution. Je ne veux pas utiliser try catch à des fins de validation
user960567
1
Vous pouvez créer un schéma pour votre JSON et le vérifier ultérieurement par rapport à ce schéma, voir: Json.NET 3.5 Beta 2 - JSON schema validation
Habib
1
Un moyen de le faire sans un bloc d'essai? Je n'utilise pas de blocs d'essai sauf si je traite avec un inconnu. Je recherche quelque chose comme JsonConvert.TryDeserializeObject. Les essais opérationnels ne sont que du mauvais code.
Jordanie
1
L' utilisation JSON.Net: Cela ne pas jeter une exception: JToken.Parse("1234")! Cela peut être une bonne idée de vérifier d'abord si la chaîne commence par [ou {. Une autre alternative est l'utilisation JObject.Parse()et JArray.Parse().
RhinoDevel
1
JToken.Parse("{a:1}")ne lève pas d' exception même s'il s'agit d'un JSON invalide - adoit être cité ( stackoverflow.com/q/949449/3116322 )
Ande
31

Utilisez la JContainer.Parse(str)méthode pour vérifier si le str est un Json valide. Si cela lève une exception, ce n'est pas un Json valide.

JObject.Parse- Peut être utilisé pour vérifier si la chaîne est un objet Json valide
JArray.Parse- Peut être utilisé pour vérifier si la chaîne est un tableau Json valide
JContainer.Parse- Peut être utilisé pour vérifier à la fois l'objet Json et le tableau

Senthilkumar Viswanathan
la source
17
Au lieu de JContainer, il est plus valide d'utiliser le type JToken puisque la méthode Parse () est déclarée à ce niveau
Denis The Menace
6
Je suppose que vous parlez de JSON.Net: JContainer ne fonctionne pas de cette façon, car il ne lèvera pas d'exception dans tous les cas souhaités. Exemple: JContainer.Parse("1234");.
RhinoDevel
Mauvaise réponse, JContainer.Parse fonctionne sur tout
Toolkit
19

En vous basant sur la réponse d'Habib, vous pouvez écrire une méthode d'extension:

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

Qui peut ensuite être utilisé comme ceci:

if(stringObject.ValidateJSON())
{
    // Valid JSON!
}
Tom Beech
la source
1
JToken.Parse(s);retourne truemême siJToken.Parse(123);
Make Makeluv
2
Retour truepour cet invalide JSON:{A:{"B": 1}}
Mehdi Dehghani
Belle méthode d'extension à avoir :) Bien qu'elle soit probablement mieux nommée "IsValidJson".
Mladen B.
11

Juste pour ajouter quelque chose à la réponse de @ Habib, vous pouvez également vérifier si le JSON donné est d'un type valide:

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
la source
7

J'ai trouvé que JToken.Parse analyse de manière incorrecte le JSON invalide tel que le suivant:

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

Collez la chaîne JSON dans http://jsonlint.com/ - elle n'est pas valide.

J'utilise donc:

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
la source
Ce n'est pas une chaîne JSON invalide ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf voici la documentation de la norme JSON ECMA et sous le point 5 Valeurs JSON, vous pouvez voir qu'une valeur peut prendre null comme valeur . Donc c'est juste un bug dans l'interpréteur jsonlint
Dominik Lemberger
4
Dominik, une valeur JSON selon ma lecture de la spécification que vous avez liée doit avoir un jeton valide, le texte nul littéral représentant une valeur nulle. Les valeurs valides sont "un objet, un tableau, un nombre, une chaîne, vrai, faux ou nul" selon la spécification que vous avez référencée. AFAICS il n'y a pas de valeur valide sans jeton de valeur.
Kirtlander
Cela semble être OK avec JSON invalide qui ressemble à ceci{ name : "l am invalid JSON" }
Jon49
2

⚠️ Option alternative n'utilisant pas JSON.Net ⚠️

Pour .Net Core / .Net 5 ( en préversion au moment de la rédaction de cet article ), on peut également utiliser l' System.Text.Jsonespace de noms et analyser en utilisant le JsonDocument. L'exemple est une méthode d'extension basée sur les opérations d'espace de noms:

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

    return false;
}
ΩmegaMan
la source
1

Concernant la réponse de Tom Beech; J'ai plutôt proposé ce qui suit:

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

Avec une utilisation des éléments suivants:

if (ValidateJSON(strMsg))
{
    var newGroup = DeserializeGroup(strMsg);
}
HappyCoding
la source
3
Ce n'est pas nouveau - vous avez fait d'une méthode d'extension pas une méthode d'extension. La réponse de Tom Beech peut déjà atteindre ce dont vous avez besoin (en général, je désapprouverais également l'ajout de méthodes d'extension de ce type string, mais cette réponse devrait vraiment soit a) ne pas être ici ou b) dire "j'ai utilisé la réponse de Tom Beech " sans le this, c'est-à-dire sans en faire un élément d'extension) - tant cette réponse que celle référencée ont une brièveté et des faiblesses identiques. Si vous devez faire valoir ce point, mettez simplement un commentaire sur l'autre réponse.
Ruben Bartelink
1

JToken.Typeest disponible après une analyse réussie. Cela peut être utilisé pour éliminer une partie du préambule dans les réponses ci-dessus et fournir un aperçu pour un contrôle plus précis du résultat. Entrée totalement invalide (par exemple, "{----}".IsValidJson();lancera toujours une exception).

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

Référence Json.Net pour JToken.Type: https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Linq_JTokenType.htm

Randy Larson
la source
0

Cette méthode ne nécessite pas de bibliothèques externes

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
la source
0

Voici une méthode d'extension TryParse basée sur la réponse de 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;
    }
}

Usage:

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

J'utilise celui-ci:

  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
la source