Wenn ich eine Anfrage an einen Dienst sende (den ich nicht besitze), antwortet dieser möglicherweise entweder mit den angeforderten JSON-Daten oder mit einem Fehler, der wie folgt aussieht:
{
"error": {
"status": "error message",
"code": "999"
}
}
In beiden Fällen ist der HTTP-Antwortcode 200 OK, daher kann ich damit nicht feststellen, ob ein Fehler vorliegt oder nicht. Ich muss die Antwort deserialisieren, um sie zu überprüfen. Ich habe also etwas, das so aussieht:
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.
// Or, it may be a successful JSON response: do nothing.
}
}
error = null;
return false;
}
Hier habe ich eine leere catch-Klausel, die sich möglicherweise im Standardausführungspfad befindet, was ein schlechter Geruch ist ... Nun, mehr als ein schlechter Geruch: Es stinkt.
Kennen Sie einen besseren Weg, um die Antwort "TryParse" zu machen, um einen Haken im Standardausführungspfad zu vermeiden ?
[BEARBEITEN]
Dank der Antwort von Yuval Itzchakov habe ich meine Methode folgendermaßen verbessert:
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;
}
}
Ich habe die catch-Klausel beibehalten ... nur für den Fall.