1

I don't know if I have done this correctly or not, but I have the following class to try to validate and parse JSON:

public static class JsonHelper
{
    internal const string UserResetDataScheme = @"{
      'title' : 'UserResetDataModel',
      'type' : 'object',
      'properties': {
        'Role' : {'type' : 'integer'},
        'Email' : {'type' : 'string'},
      },
      required: [ 'Role', 'Email']
    }";

    internal static T TryParseJson<T>(this string json, string schema) where T : new()
    {
        var parsedSchema = JSchema.Parse(schema);
        var jObject = JObject.Parse(json);

        return jObject.IsValid(parsedSchema) ? JsonConvert.DeserializeObject<T>(json) : default(T);
    }
}

Most of the time the schema check works fine, but sometimes I need to deserialize a string like this:

"\"User sent null or empty data\""

In that case the schema validation should return false. However, I get an error when I call JObject.Parse:

Newtonsoft.Json.JsonReaderException: 'Error reading JObject from JsonReader. Current JsonReader item is not an object: String. Path '',

I am using the schema which I have shown above.

If I understand this right, I can't parse to string? But then what do I do in this case? How can I validate the JSON is incorrect if I can't parse it?

(JSON which conforms to this schema parses correctly.)

3
  • What is the JSON string you are trying to parse/validate against the schema? Commented Sep 19, 2019 at 20:05
  • I wrote this line: -- well I check schema works fine but sometimes I need to deserialize the string like "\"User sent null or empty data\"" Commented Sep 20, 2019 at 5:14
  • OK, I see now what is going on. I've added an answer. Commented Sep 20, 2019 at 5:57

1 Answer 1

1

You are getting an error because "\"User sent null or empty data\"" is not a JSON object, so it cannot be parsed by JObject.Parse. Instead you should use JToken.Parse. This method can handle any kind of JSON -- objects, arrays and simple values. The IsValid extension method is defined to work on JToken, so it should still work fine with this change.

As an aside, when the JToken validates successfully, you don't need to deserialize the JSON a second time with JsonConvert.DeserializeObject<T>(). You can convert the token to your object directly using JToken.ToObject<T>() instead.

So in other words, change this code:

var jObject = JObject.Parse(json);
return jObject.IsValid(parsedSchema) ? JsonConvert.DeserializeObject<T>(json) : default(T);

To this:

var jToken = JToken.Parse(json);
return jToken.IsValid(parsedSchema) ? jToken.ToObject<T>() : default(T);

To be extra safe you could put a try/catch block around the parsing. That way if you get a string that isn't even JSON at all, you can handle that as well. So then you would have:

internal static T TryParseJson<T>(this string json, string schema) where T : new()
{
    var parsedSchema = JSchema.Parse(schema);
    try
    {
        var jToken = JToken.Parse(json);
        return jToken.IsValid(parsedSchema) ? jToken.ToObject<T>() : default(T);
    }
    catch (JsonException ex)
    {
        // optionally log the exception here
        return default(T);
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Without any problems (return default), thank's for your answer)!

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.