前提
あるAPIと通信し、結果を返すモジュールを作成しています。
APIはjson形式で結果を返し、モジュール内でJson.NETを使ってエンティティクラスにデシリアライズを行っています。
モジュールでは複数のAPI呼び出しがあり、レスポンスのエンティティクラスは一つの抽象クラスを継承し、APIごとに作成しています。
発生している問題・エラーメッセージ
APIはリクエストを正常に処理すると、下記の様なレスポンスを返すのですが、
JSON
1{ 2 "token": "abcdefghijklmnopqrstuvwxyz" 3}
リクエストを処理できなかった場合、下記の様なレスポンスを返します。
JSON
1[ 2 { 3 "error_code": "E01", 4 "error_information": "hogehoge" 5 }, 6 { 7 "error_code": "E02", 8 "error_information": "mogemoge" 9 } 10]
どのAPIでもエラー時に返ってくるデータのフォーマットは同一なので、すべてのレスポンスクラスの親は下記のような実装になっています。
c#
1public abstract class Response 2{ 3 public Error[] Errors { get; set; } 4 5 public class Error 6 { 7 [JsonProperty("error_code")] 8 public string ErrorCode { get; set; } 9 10 [JsonProperty("error_information")] 11 public string ErrorInformation { get; set; } 12 } 13}
各APIのレスポンスクラスはこのように実装しています。
C#
1public class HogeApiResponse : Response 2{ 3 [JsonProperty("token")] 4 public string Token { get; set; } 5}
しかし、上記のコードでは、エラー時のJSONをデシリアライズできず、例外が発生してしまいます。
Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'toybox.Response' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly. To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List<T> that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.
試したこと
エラーメッセージに従って、ResponseクラスにIEnumerable<Error>を実装したりJsonArrayをつけたりしてみましたが正常にデシリアライズはできませんでした。
実現したいこと
APIがエラーを返したとき、他のプロパティはNull等でも構わないのでError[]にエラー情報が格納された状態でデシリアライズを行いたいです。
実際のコードではジェネリック等使って型を識別しているので、なんとか一つのクラスへのデシリアライズで完結させたいと思っています。
検証用のコード
実際のコードでテストするのは時間がかかるので、コンソールアプリを一つ作ってテストしています。
同じ様な例外が飛びます。
C#
1using System.Collections.Generic; 2using Newtonsoft.Json; 3 4namespace toybox 5{ 6 static class Program 7 { 8 static void Main(string[] args) 9 { 10 var r = JsonConvert.DeserializeObject<ResponseImpl>(@"[{""error_code"":""E01"",""error_information"":""hogemoge""}]"); 11 } 12 } 13 14 public abstract class Response 15 { 16 public List<Error> Errors { get; set; } 17 18 public class Error 19 { 20 [JsonProperty("error_code")] 21 public string ErrorCode { get; set; } 22 23 [JsonProperty("error_information")] 24 public string ErrorInformation { get; set; } 25 } 26 } 27 28 public class ResponseImpl : Response 29 { 30 31 } 32} 33
補足情報(FW/ツールのバージョンなど)
.NET Framework 4.5.2
回答3件
あなたの回答
tips
プレビュー