反序列化JSON在"的TryParse"方法 [英] Deserialize json in a "TryParse" way
问题描述
当我请求发送到一个服务(即我没有自己)可能既响应与请求JSON数据,无论是与一个JSON的错误,看起来像这样:
When I send a request to a service (that I do not own) it may responds either with the json data requested, either with a json error that looks like that :
{
"error": {
"status": "error message",
"code": "999"
}
}
在这两种情况下, HTTP响应code 是 200确定。 所以,我不能依赖它,我要反序列化的反应来检查它是否是一个错误或没有。 所以,我有东西,看起来像这样:
In these two cases, HTTP response code is 200 OK. So, I cannot rely on it, i have to deserialize the response to check whether it is an error or not. So I have something that looks like that :
bool TryParseResponseToError(string jsonResponse, out Error error)
{
// Check expected error keywords presence
// before try clause to avoid catch performance drawbacks
if (jsonResponse.Contains("error") &&
jsonResponse.Contains("status") &&
jsonResponse.Contains("code"))
{
try
{
error = new JsonSerializer<Error>().DeserializeFromString(jsonResponse);
return true;
}
catch
{
// The JSON response seemed to be an error, but failed to deserialize.
// It may be a successful JSON response : do nothing.
}
}
error = null;
return false;
}
在这里,我有一个空的catch子句可能在标准执行路径,这是一个不好的气味......好了,多了难闻的气味:太臭
Here, I have an empty catch clause that may be in the standard execution path, which is a bad smell... Well, more than a bad smell : it stinks.
你知道一个更好的方式为的TryParse,以便响应避免在标准的执行路径的catch
Do you know a better way to "TryParse" the response in order to avoid a catch in the standard execution path ?
由于尤瓦Itzchakov 的答案,我提高了我的方法,这样的:
Thanks to Yuval Itzchakov's answer I improved my method like that :
bool TryParseResponse(string jsonResponse, out Error error)
{
// Check expected error keywords presence :
if (!jsonResponse.Contains("error") ||
!jsonResponse.Contains("status") ||
!jsonResponse.Contains("code"))
{
error = null;
return false;
}
// Check json schema :
const string errorJsonSchema =
@"{
'type': 'object',
'properties': {
'error': {'type':'object'},
'status': {'type': 'string'},
'code': {'type': 'string'}
},
'additionalProperties': false
}";
JsonSchema schema = JsonSchema.Parse(errorJsonSchema);
JObject jsonObject = JObject.Parse(jsonResponse);
if (!jsonObject.IsValid(schema))
{
error = null;
return false;
}
// Try to deserialize :
try
{
error = new JsonSerializer<Error>.DeserializeFromString(jsonResponse);
return true;
}
catch
{
// The JSON response seemed to be an error, but failed to deserialize.
// This case should not occur...
error = null;
return false;
}
}
我不停的catch子句...以防万一。
I kept the catch clause... just in case.
推荐答案
通过 Json.NET
可以验证对架构的JSON:
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
}
,然后使用一个的TryParse方法内
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);
if (!jObject.IsValid(parsedSchema))
{
return default(T);
}
return (T)JsonConvert.DeserializeObject(json);
}
然后执行:
var myType = myJsonString.TryParseJson<AwsomeType>(schema);
这篇关于反序列化JSON在&QUOT;的TryParse&QUOT;方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!