背景
GMOコインのAPIでアプリを作ろうと思った際に、レスポンスの辞書のキーが多くてデコード用の型を書くのが大変だったため、楽に書ける方法を考えてみた。
普通にデコード用の構造体を作る場合
例えば、marginデータを取得したいときのパスとそのレスポンスは下記になる。
このレスポンスをデコードする場合は下記のようにデコード用の構造体を作る必要がある。
/private/v1/account/margin のレスポンス
{
"status": 0,
"data": {
"actualProfitLoss": "5204923",
"availableAmount": "5189523",
"margin": "7298",
"marginCallStatus": "NORMAL",
"marginRatio": "345.6",
"profitLoss": "8019"
},
"responsetime": "2019-03-19T02:15:06.051Z"
}
デコード用の構造体
struct Margin: Codable {
var status: Int
var data: MarginData
var responsetime: String
}
struct MarginData {
var actualProfitLoss: String
var availableAmount: String
var margin: String
var marginCallStatus: String
var marginRatio: String
var profitLoss: String
}
// デコード
let decodedData = try! JSONDecoder().decode(Margin.self, from: jsonData)
これでも問題ないのだが、margin以外にもアクセスしたいパスが沢山あり、それらのレスポンスに対していちいちレスポンスのキーを調べて書くのが大変だったため、楽にかける方法を考えてみた。
極力簡単にデコード用の構造体を作る方法
ネストのうち、同一階層のデータの型が同じであれば、下記のようにDictionaryで指定してあげれば、辞書の長さに関係なく一行で書くことができる。
struct Margin: Codable {
var status: Int
var data: Dictionary<String, String>
// var data: [String: String] でもいける
var responsetime: String
}
その他
いちいちデコード用の型を指定する必要があるということは、そうしないと不都合があるのでは?とも思うため、これはこれで何か落とし穴がありそう。
この書き方で懸念されるバグなどあれば教えていただきたいです。