210

I have a raw string. I just want to validate whether the string is valid JSON or not. I'm using JSON.NET.

wonea
  • 4,783
  • 17
  • 86
  • 139
Imran Qadir Baksh - Baloch
  • 32,612
  • 68
  • 179
  • 322

13 Answers13

284

Through Code:

Your best bet is to use parse inside a try-catch and catch exception in case of failed parsing. (I am not aware of any TryParse method).

(Using JSON.Net)

Simplest way would be to Parse the string using JToken.Parse, and also to check if the string starts with { or [ and ends with } or ] respectively (added from this answer):

private static bool IsValidJson(string strInput)
{
    if (string.IsNullOrWhiteSpace(strInput)) { 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;
    }
}

The reason to add checks for { or [ etc was based on the fact that JToken.Parse would parse the values such as "1234" or "'a string'" as a valid token. The other option could be to use both JObject.Parse and JArray.Parse in parsing and see if anyone of them succeeds, but I believe checking for {} and [] should be easier. (Thanks @RhinoDevel for pointing it out)

Without JSON.Net

You can utilize .Net framework 4.5 System.Json namespace ,like:

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

(But, you have to install System.Json through Nuget package manager using command: PM> Install-Package System.Json -Version 4.0.20126.16343 on Package Manager Console) (taken from here)

Non-Code way:

Usually, when there is a small json string and you are trying to find a mistake in the json string, then I personally prefer to use available on-line tools. What I usually do is:

Oleksii
  • 1,479
  • 1
  • 19
  • 35
Habib
  • 219,104
  • 29
  • 407
  • 436
  • 5
    How can do this at runtime. I don't want to use try catch for validation purpose – Imran Qadir Baksh - Baloch Feb 20 '13 at 10:49
  • 1
    You can create a Schema for your JSON and later verify against that schema see: [Json.NET 3.5 Beta 2 – JSON schema validation](http://james.newtonking.com/archive/2009/01/04/json-net-3-5-beta-2-json-schema-validation.aspx) – Habib Feb 20 '13 at 10:51
  • Why schema? I need to validate JSON generally. – Imran Qadir Baksh - Baloch Feb 20 '13 at 10:53
  • 2
    Any way to do it without a try block? I don't use try blocks unless I'm dealing with an unknown. I am looking for something like JsonConvert.TryDeserializeObject. Operational try catches are just plain bad code. – Jordan Apr 09 '15 at 19:36
  • @Jordan, I agree, `TryParse` group of methods should always be used if available. Here they are not. So `try-catch` is the only way possible, or if you want to write your own deserializer... One more thing to add, if you are trying to validate json, then probably you are dealing with *unknown* – Habib Apr 09 '15 at 19:40
  • It is a known in that it is information that is conceivably available to and constant within the scope of the current thread or application. If it is a condition (i.e., this JSON text is valid) that is guaranteed to remain true or false for the life of the work unit, you do not need a try catch. On the other hand if it is something that is not guaranteed to be constant (i.e. does this file exists, do I have an internet connection, ect...), then that does require a try catch construct. – Jordan Apr 10 '15 at 17:05
  • Nice answer. However, I've got an issue where I want to pass my JSON through to node.js when the JSON string is valid. Unfortunately, node.js is rather more strict: it does not deal with floating commas in JSON arrays, and with irregular whitespace characters (like \u00a0, non-breaking space). For the moment, I'm deserializing and serializing to work around, but that seems a bit of a heavy solution for what I want. Any way to do this without the reserialization step? – Kenny Hung Apr 27 '15 at 15:49
  • @KennyHung, It sounds like something that needs tweaking at node.js end, unfortunately I don't have any experience with node.js, may be you can ask a new question with respect to node.js, provide an example that should be good at C# end but fails at node.js, I hope you will get the answer from the community. – Habib Apr 27 '15 at 15:54
  • @Habib, thanks for the suggestion. It's Google's V8 engine's implementation of JSON.parse that I'm using (obviously, because it's in node), and there doesn't seem to be a way to tell it to be 'less strict'. It's worth noting that irregular whitespace characters, floating commas and single quotes are **not** valid JSON, and these C# solutions seem to be just more tolerant (as is, perhaps, common in the Windows world). – Kenny Hung May 06 '15 at 19:56
  • 2
    **Using JSON.Net:** This does **not** throw an exception: `JToken.Parse("1234")`! Might be a good idea to check first, if string starts with `[` or `{`. Another alternative is use `JObject.Parse()` and `JArray.Parse()`. – RhinoDevel Nov 24 '15 at 08:26
  • @RhinoDevel, that is an excellent point. I never knew that `JToken.Parse` would behave like that. After looking at the documentation `JToken.Parse` would have worked for `"'a astring'"` as well. Modified my answer accordingly. Thanks again for pointing it out. – Habib Nov 24 '15 at 17:58
  • No need to check for `{` and `[`. Just use `JToken.Parse` and check, it the return value is `JObject` or `JArray`. – xmedeko Mar 03 '16 at 08:09
  • @RhinoDevel I don't understand... Why "1234" isn't a valid JSON string? If this is the case, then what is the JSON representation of the number 1234? Or the boolean value false ? I've done some digging and according to the latest spec [RFC 7159](https://tools.ietf.org/html/rfc7159#page-15) JSON allows simple values like numbers etc. To quote from the changes section on page 14: "Changed the definition of "JSON text" so that it can be any JSON value, removing the constraint that it be an object or array." – Vasea Mar 10 '16 at 15:31
  • 2
    `JToken.Parse("{a:1}")` does **not** throw exception even though this is invalid JSON - `a` should be quoted (http://stackoverflow.com/q/949449/3116322) – Ande Mar 10 '16 at 16:17
  • @Vasea: Isn't RFC 7159 just a proposed standard ([see here](http://www.rfc-editor.org/info/rfc7159))? I got my information from [json.org](json.org) where there is a link to the [ECMA-404 Standard](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). I am not really sure about how the whole standardization stuff works, but this is the side e.g. [Douglas Crockford](http://crockford.com/) is referencing.. – RhinoDevel Mar 10 '16 at 17:01
  • @RhinoDevel JSON standards are confusing to me too. It seems that ECMA-404 does allow json text, but it's not allowed if used as an internet media type [https://www.quora.com/Is-Text-valid-JSON-by-itself](https://www.quora.com/Is-Text-valid-JSON-by-itself) – Vasea Mar 10 '16 at 17:41
  • Potentially expensive check since you will most likely just repeat it if it returns true; I would return a successResult object with a `bool success` and `object result` so that the parse isn't repeated. – Dagrooms Feb 14 '17 at 17:01
  • Definitely doesnt work for me trying to Parse a "JSON" String with 2 "Head" Elements on the Top Level just ignores it and automatically cuts off 1 of the 2 Head Elements - Therefore not Validating the JSON wrong, but making it right itself, by just overwriting the dictionary the json is safed in. Using C# with Newtonsoft (exact code above) – Dominik Lemberger Mar 23 '17 at 07:39
  • 1
    catch (Exception ex) //some other exception ... What is some other exception? JToken.Parse only throws a JsonReaderException. It is possible that a null value might throw a null pointer exception when JToken.Parse is creating the creating the StringReader under the hood, but even if that is the case that will throw an error when you try strInput.Trim() which is outside the try block. – stephenbayer Aug 12 '19 at 17:16
  • 1
    The question asked how to check if it's valid JSON, not if it's a valid JSON object or array. Isn't "1234" being valid JSON the reason that it doesn't throw an exception? – Kyle Delaney Jan 07 '20 at 21:31
  • Yeah, `1234` is perfectly valid JSON in the general case, even by itself. Certain specific sources may want a full key-value object with curly braces, but in the general case, a JSON instance can be a primitive as well. – Panzercrisis Jan 29 '21 at 17:19
  • beware that JSON.Net does not throw an exception when parsing lists with trailing commas. This is a [known issue](https://github.com/JamesNK/Newtonsoft.Json/issues/818). – mulllhausen Aug 23 '21 at 08:23
44

Use JContainer.Parse(str) method to check if the str is a valid Json. If this throws exception then it is not a valid Json.

JObject.Parse - Can be used to check if the string is a valid Json object
JArray.Parse - Can be used to check if the string is a valid Json Array
JContainer.Parse - Can be used to check for both Json object & Array

Brian Rogers
  • 125,747
  • 31
  • 299
  • 300
  • 19
    Instead of JContainer it's more valid to use type JToken since Parse() method is declared at this level – Denis The Menace Feb 09 '15 at 12:40
  • 7
    I am assuming that you are talking about JSON.Net: JContainer does **not** work that way, because it won't throw an exception in all wanted cases. Example: `JContainer.Parse("1234");`. – RhinoDevel Nov 24 '15 at 08:43
  • 2
    `1234` is valid JSON. Some specific sources may want a full key-value "dictionary" surrounded in curly braces, but in the general case, primitives are okay as well. – Panzercrisis Jan 29 '21 at 17:16
38

Building on Habib's answer, you could write an extension method:

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

Which can then be used like this:

if(stringObject.ValidateJSON())
{
    // Valid JSON!
}
Tom Beech
  • 2,289
  • 1
  • 21
  • 25
16

Just to add something to @Habib's answer, you can also check if given JSON is from a valid type:

public static bool IsValidJson<T>(this string strInput)
{
    if(string.IsNullOrWhiteSpace(strInput)) return false;

    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
  • 6,594
  • 9
  • 63
  • 100
  • 1
    I suggest to add in the if "strInput != null && ..." because StartsWith and "EndsWith can trigger an ArgumentNullException. – Marco Concas Jan 21 '21 at 17:38
13

I found that JToken.Parse incorrectly parses invalid JSON such as the following:

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

Paste the JSON string into http://jsonlint.com/ - it is invalid.

So I use:

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;
}
Ciarán Bruen
  • 5,221
  • 13
  • 59
  • 69
Andrew Roberts
  • 990
  • 2
  • 12
  • 26
  • Thats not an invalid JSON String http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf here is the documentation of the JSON Standard ECMA and under Point 5 JSON Values you can see a value can take null as value. So its just a bug in the jsonlint interpreter – Dominik Lemberger Mar 23 '17 at 07:53
  • 4
    Dominik, a JSON value according to my read of the spec you linked must have some valid token, with the literal null text representing a null value. Valid values are "an object, array, number, string, true, false, or null" according to the spec you referenced. AFAICS there is no valid value with no value token. – Kirtlander Nov 07 '17 at 18:36
  • This looks like it will be OK with invalid JSON which looks like this `{ name : "l am invalid JSON" }` – Jon49 Mar 27 '19 at 19:29
9

⚠️ Alternate option using System.Text.Json ⚠️

For .Net Core one can also use the System.Text.Json namespace and parse using the JsonDocument. Example is an extension method based on the namespace operations:

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

    return false;
}
ΩmegaMan
  • 29,542
  • 12
  • 100
  • 122
  • 1
    `JsonDocument` is disposable. Failure to do so will *[result in the memory not being returned to the (memory) pool, which will increase GC impact across various parts of the framework.](https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsondocument?view=net-5.0)*, according to the docs. So you need to add a `using` in there somewhere. – dbc Aug 11 '21 at 21:16
  • True and good to know, but the document in question is never assigned, so there is no **held** reference to it and the GC may not clean it up when scope of the method is done, but it will be lazily collected when the system decides its needs memory. With that said, if the usage of this method will encounter very large json items or many of them... then placing this *example* into a dispose pattern with a `using` would be an excellent idea. – ΩmegaMan Aug 11 '21 at 22:28
  • 2
    Throwing exceptions for validating business rules as commonplace as checking a JSON string is an unacceptable disregard for the overall performance of the application. Exceptions are expensive, computationally speaking. – Silvair L. Soares Oct 20 '21 at 14:07
  • @SilvairL.Soares I fully agree with your statement. Fortunately this call would only be done once per data set per session. If there is a better way...I hope someone presents it here. :-/ – ΩmegaMan Oct 20 '21 at 14:12
3

Regarding Tom Beech's answer; I came up with the following instead:

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

With a usage of the following:

if (ValidateJSON(strMsg))
{
    var newGroup = DeserializeGroup(strMsg);
}
Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
HappyCoding
  • 641
  • 16
  • 36
  • 5
    This is not novel - you made an extension method not be an extension method. Tom Beech's answer can already achieve what you need (In general, I'd also frown on adding extension methods of this kind on `string`, but this answer really should either a) not be here or b) say "I used [Tom Beech's answer](https://stackoverflow.com/a/31404282/11635)" without the `this`, i.e. without making it an extension member) - both this answer and the referenced one have identical brevity and weaknesses. If you must make this point, just put a comment on the other answer. – Ruben Bartelink Mar 27 '19 at 03:48
2

JToken.Type is available after a successful parse. This can be used to eliminate some of the preamble in the answers above and provide insight for finer control of the result. Entirely invalid input (e.g., "{----}".IsValidJson(); will still throw an 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;
        }
    }

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

Randy Larson
  • 6,817
  • 2
  • 18
  • 13
0

This method doesn't require external libraries

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
  • 43
  • 8
0

Here is a TryParse extension method based on Habib's answer:

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
  • 1,363
  • 1
  • 12
  • 23
0

I'm using this one:

  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
  • 4,532
  • 4
  • 53
  • 64
0

Extension that returns a json string even if it returns an exception:

        public static string OnlyValidJson(this string strInput)
        {
            if (string.IsNullOrWhiteSpace(strInput)) { return @"[""Json is empty""]"; }
            strInput = strInput.Trim();
            if ((strInput.StartsWith("{") && strInput.EndsWith("}")) ||
                (strInput.StartsWith("[") && strInput.EndsWith("]")))
            {
                try
                {
                    string strEscape = strInput.Replace("\\n", "").Replace("\\r", "").Replace("\n", "").Replace("\r", "");
                    JToken.Parse(strEscape);
                    return strEscape;
                }
                catch (JsonReaderException jex)
                {
                    return @$"{{""JsonReaderException"":""{jex.Message}""}}";
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                    return @$"{{""Exception"":""{ex.ToString()}""}}";
                }
            }
            else
            {
                return @"[""Json not start with { or [.""]";
            }
        }

0

Sometime JToken.Parse(jsonString); doesnt validate the json completely.

instead you can use below method to check validity of json string while reading. Ref : https://www.newtonsoft.com/jsonschema/help/html/ValidatingJson.htm

string json = @"{
  'name': 'James',
  'hobbies': ['.NET', 'Blogging', 'Reading', 'Xbox', 'LOLCATS']
}";

JsonTextReader reader = new JsonTextReader(new StringReader(json));

JSchemaValidatingReader validatingReader = new JSchemaValidatingReader(reader);
validatingReader.Schema = JSchema.Parse(schemaJson);

IList<string> messages = new List<string>();
validatingReader.ValidationEventHandler += (o, a) => messages.Add(a.Message);

JsonSerializer serializer = new JsonSerializer();
Person p = serializer.Deserialize<Person>(validatingReader);
Dan Atkinson
  • 11,391
  • 14
  • 81
  • 114
S G
  • 1
  • 5