1. ホーム
  2. c#

[解決済み] TryParse方式でjsonをデシリアライズする

2023-04-15 12:30:58

質問

私が所有していない)サービスにリクエストを送信すると、要求されたJSONデータで応答するか、または次のようなエラーで応答することがあります。

{
    "error": {
        "status": "error message",
        "code": "999"
    }
}

どちらの場合も、HTTPレスポンスコードは200 OKなので、これではエラーがあるかどうか判断できません。 そこで、次のようなものを用意しました。

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

ここで、標準的な実行パスにあるかもしれない空のcatch節がありますが、これは悪い匂いです...。まあ、悪臭というより、臭いですね。

の良い方法をご存知ですか? "TryParse"。 を行うために、レスポンスを キャッチを避ける を避けるためです。

[EDIT】をご覧ください。]

感謝 Yuval Itzchakov の回答を見て、そのように改善しました。

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節は残しておきました...念のため。

どのように解決するのですか?

とは Json.NET を使うと、スキーマに照らし合わせてjsonを検証することができます。

 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メソッド内で使用します。

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

では、そうしてください。

var myType = myJsonString.TryParseJson<AwsomeType>(schema);

更新しました。

スキーマ検証はNewtonsoft.Jsonのメインパッケージに含まれなくなったことに注意してください。 Newtonsoft.Json.Schemaを追加する必要があります。 パッケージを追加する必要があります。

更新2:

コメントにあるように、"JSONSchema" は価格モデルを持っています、つまり 無料ではありません。 . すべての情報を見ることができます はこちら