Deserialize json in a "TryParse" way
With Json.NET
you can validate your json against a schema:
string schemaJson = @"{ 'status': {'type': 'string'}, 'error': {'type': 'string'}, 'code': {'type': 'string'}}";JsonSchema schema = JsonSchema.Parse(schemaJson);JObject jobj = JObject.Parse(yourJsonHere);if (jobj.IsValid(schema)){ // Do stuff}
And then use that inside a TryParse method.
public static T TryParseJson<T>(this string json, string schema) where T : new(){ JsonSchema parsedSchema = JsonSchema.Parse(schema); JObject jObject = JObject.Parse(json); return jObject.IsValid(parsedSchema) ? JsonConvert.DeserializeObject<T>(json) : default(T);}
Then do:
var myType = myJsonString.TryParseJson<AwsomeType>(schema);
Update:
Please note that schema validation is no longer part of the main Newtonsoft.Json package, you'll need to add the Newtonsoft.Json.Schema package.
Update 2:
As noted in the comments, "JSONSchema" have a pricing model, meaning it isn't free. You can find all the information here
@Victor LG's answer using Newtonsoft is close, but it doesn't technically avoid the a catch as the original poster requested. It just moves it elsewhere. Also, though it creates a settings instance to enable catching missing members, those settings aren't passed to the DeserializeObject call so they are actually ignored.
Here's a "catch free" version of his extension method that also includes the missing members flag. The key to avoiding the catch is setting the Error
property of the settings object to a lambda which then sets a flag to indicate failure and clears the error so it doesn't cause an exception.
public static bool TryParseJson<T>(this string @this, out T result) { bool success = true; var settings = new JsonSerializerSettings { Error = (sender, args) => { success = false; args.ErrorContext.Handled = true; }, MissingMemberHandling = MissingMemberHandling.Error }; result = JsonConvert.DeserializeObject<T>(@this, settings); return success;}
Here's an example to use it:
if(value.TryParseJson(out MyType result)){ // Do something with result…}
A slightly modified version of @Yuval's answer.
static T TryParse<T>(string jsonData) where T : new(){ JSchemaGenerator generator = new JSchemaGenerator(); JSchema parsedSchema = generator.Generate(typeof(T)); JObject jObject = JObject.Parse(jsonData); return jObject.IsValid(parsedSchema) ? JsonConvert.DeserializeObject<T>(jsonData) : default(T);}
This can be used when you don't have the schema as text readily available for any type.