いくつかの統計情報を返すAPIエンドポイントがあります。現在、応答は次のようになります。
オプション1:
{
"stats": [
{
"name": "some-stats-key1",
"value": 10
},
{
"name": "some-stats-key2",
"value": 20
}
],
... other keys
}
しかし、これは少し複雑に見え、私はそれをどのようにするのか:
オプション2:
{
"stats": {
"some-stats-key1": 10,
"some-stats-key2": 20
}
... other keys
}
オプション1は拡張が簡単ですが、ユーザーにとって快適ではないことを理解しています。これらのオプションのいずれかを使用して直面する可能性がある他の問題は何ですか?または、次のようなハイブリッドソリューションを作成する必要があります。
オプション3:
{
"stats": {
"some-stats-key1": {
"name": "some-stats-key1",
"value": 10
},
"some-stats-key2": {
"name": "some-stats-key2",
"value": 20
},
},
... other keys
}
キー「some-stats-key1」と「some-stats-key2」は単なる内部値であり、APIユーザーがドキュメントを使用して、それらを読み取り可能な名前にマッピングすることが期待されています。すべてのキーは一意です。
「統計」の順序は重要ではありません。
典型的な使用例は、すべての統計情報を取得し、キーを判読可能な名前と照合し、Webページにテーブルとして表示することです。しかし、現在のところ、統計の一部だけが必要になる人がいないかどうかは、現時点ではわかりません。
この問題のベストプラクティスはありますか?
オプション2を選びます。APIコンシューマーがsome-stats-key1
読み取り可能なものに変換します。これは、おそらく彼/彼女が関心のある値のリストを持っていることを意味します(たとえば、some-stats-key1
およびsome-stats-key3
)、そのリストを反復処理します。 JSONオブジェクトを選択することにより、APIのコンシューマーに便利なルックアップを提供するディクショナリ/マップとしてデシリアライズされます。
これは、コンシューマーがJSON配列を反復処理するか、興味深いキーを使用して独自のディクショナリーを事前に作成する必要があるオプション1では、より面倒になります。
オプション3は私には少々冗長すぎます。キー名の重複は私にとって魅力的ではありません。
拡張性が懸念される場合は、いつでもAPIのv2を公開して次のようなものを返すことができます
"stats": {
"some-stats-key1": { "value": 10, "error-margin": 0.1 },
"some-stats-key2": { "value": 20, "error-margin": 0.2 }
}
下位互換性のためにv1を保持します。 APIの使用方法を完全に制御できない場合、単一バージョンのAPI内で下位互換性を維持することは、本当のPITAになる可能性があります。追加の(オプションの)キーと値のペアを追加したとき(つまり、構造を変更しなかったとき)、私の「break」というAPIの消費を確認しました。
2つのオプションには、従来のリストとマップの利点があります。
1)リストは重複したエントリを許可し、順序を維持します。これらの機能が重要な場合は、扱いにくいもののリストを使用してください。
2)マップでは重複を許可していません。少し手間をかけるだけで注文を維持できます。大きな利点は、データ形式がより単純になることであり、特定の要素の検索は簡単です。
私のデフォルトの選択は常にシンプルなマップですが、YMMVです。
APIからデータを取得するとき、私はalwaysをチェックして、すべてが期待どおりであることを確認します。したがって、あなたのデータを処理する私の努力は、検証と実際の処理で構成されています。
ケース1では、以下を確認する必要があります。配列があります。 b。配列内のすべてのアイテムは辞書です。 c。すべての辞書にはキー「名前」があります。 d。 「名前」キーのすべての値は一意です。
ケース3では、以下を確認する必要があります。辞書があります。 b。辞書内のすべての値は辞書です。 c。各ディクショナリには、外部ディクショナリのキーと一致する値を持つキー「名前」があります。やや良い。
ケース2では、以下を確認する必要があります。辞書があります。
(もちろん、値もチェックする必要があります)。したがって、あなたのケース2は、私の側で最小限のチェックを必要とします。私は実際にすぐに使用できるデータ構造を取得します。
2の唯一の問題は、拡張できないことです。そのため、値を数値として送信する代わりに、{value:10}を送信することができます。これは、下位互換性のある方法で拡張できます。
冗長性が悪い。冗長性が実現する唯一のことは、より多くのコードを記述させることと、冗長ビットが一致しない場合の対処法を考えさせることです。バージョン2には冗長性がありません。
API設計の推奨事項を尋ねたので、
だから、あなたが提案した構造を考えると、私が実装する構造はこれに似たものになるでしょう
[
{ /* returns only the 'common' metrics */
"stats": [
{"key":"some-metric1","value":10},
{"key":"some-metric2","value":20}
]
},
{ /* returns an optional metric in addition to the "common" metrics */
"stats": [
{"key":"some-metric1","value":15},
{"key":"some-metric2","value":5},
{"key":"some-optional-metric", "value":42}
]
},
{ /*returns the 'common' metrics as well as 2 candidates for "foo-bar" */
"stats": [
{"key":"some-metric1", "value": 5},
{"key":"some-metric2", "value": 10},
{"key":"foo-bar-candidate", "value": 7},
{"key":"foo-bar-candidate", "value": 11}
]
}
]