223

How can one validate whether a raw string is valid JSON or just text? I'm using JSON.NET.

15 Answers 15

297

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:

Sign up to request clarification or add additional context in comments.

23 Comments

How can do this at runtime. I don't want to use try catch for validation purpose
You can create a Schema for your JSON and later verify against that schema see: Json.NET 3.5 Beta 2 – JSON schema validation
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.
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().
JToken.Parse("{a:1}") does not throw exception even though this is invalid JSON - a should be quoted (stackoverflow.com/q/949449/3116322)
|
45

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

3 Comments

Instead of JContainer it's more valid to use type JToken since Parse() method is declared at this level
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");.
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.
43

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

5 Comments

JToken.Parse(s); returns true even if JToken.Parse(123);
Return true for this invalid JSON: {A:{"B": 1}}
Nice extension method to have :) Though it would probably be better named as "IsValidJson".
123 is valid JSON. It doesn't have to be a full key-value object.
Beware that this does NOT fully check the integrity of a more complex JSON object!
18

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

2 Comments

I suggest to add in the if "strInput != null && ..." because StartsWith and "EndsWith can trigger an ArgumentNullException.
For anyone reading along, the answer was edited after the comment about possible null exceptions.
15

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

5 Comments

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., according to the docs. So you need to add a using in there somewhere.
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.
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.
@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. :-/
@SilvairL.Soares I notice that every single answer here relies on catching an exception. Sometimes breaking a principal is just the most reasonable and pragmatic solution.
14

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

3 Comments

Thats not an invalid JSON String 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, 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.
This looks like it will be OK with invalid JSON which looks like this { name : "l am invalid JSON" }
4

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

1 Comment

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" 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.
3

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

Comments

2

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
}

Comments

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

Comments

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

Comments

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 [.""]";
            }
        }

1 Comment

and how this answers the question?
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);

Comments

0

Yet another way using VB.


    Public Function IsValidJson(s As String) As Boolean
        Try
            Dim jsonData = CType(JsonConvert.DeserializeObject(s), JObject)
        Catch ex As Exception
            Return False
        End Try
        Return True
    End Function

Comments

-3

I realize that this answer is 11 years old, which is way before System.Text.Json. There just has to be a better way. Full disclosure, I asked ChatGDP for a means of doing this using C# and the System.Text.JSON namespace, and voila:

{ using System; using System.Text.Json;

public class JsonValidator { public static bool IsValidJson(string json) { if (string.IsNullOrWhiteSpace(json)) { return false; }

    try
    {
        using (JsonDocument document = JsonDocument.Parse(json))
        {
            // The JSON is valid if we reach this point without exceptions
            return true;
        }
    }
    catch (JsonException)
    {
        // The JSON is invalid
        return false;
    }
}

public static void Main()
{
    string jsonString = "{ \"name\": \"John\", \"age\": 30 }";

    if (IsValidJson(jsonString))
    {
        Console.WriteLine("Valid JSON.");
        // Proceed with deserialization
    }
    else
    {
        Console.WriteLine("Invalid JSON.");
        // Handle the error
    }
}

}

}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.