Jakiej struktury JSON należy użyć dla par kluczowych wartości?

23

Jaki format JSON jest lepszym wyborem dla par klucz-wartość i dlaczego?

[{"key1": "value1"}, {"key2": "value2"}]

Lub:

[{"Name": "key1", "Value": "value1"}, {"Name": "key2", "Value": "value2"}]

Lub:

{"key1": "value1", "key2": "value2"}

Pierwszy wariant wydaje się bardziej zwarty i „semantycznie znaczący”. Drugi wariant wydaje się bardziej wyrównany, co może pomóc w jego przetworzeniu. Trzeci wariant wydaje się jeszcze bardziej semantyczny.

Pary klucz-wartość zostaną wykorzystane do dołączenia dowolnych danych do innego elementu. Dane muszą być serializowane jako JSON, aby zaokrąglić je przez system.

boot4life
źródło
3
Jeśli nie potrzebujesz zamówienia, dlaczego nie rozważyć {"key1": "value1", "key2": "value2"}?
kennytm
4
JSON jest już słownikiem (zagnieżdżalnym).
Kasey Speakman
1
Twój problem polega na tym, że opis jest na tyle szeroki, że można powiedzieć, że którykolwiek z tych formatów będzie działał, a prawdziwe pytanie brzmi, jak ułatwić korzystanie z niego, w zależności od technologii używanych przez klientów.
scriptin
Powinieneś użyć najprostszego, który spełnia twoje potrzeby, mam nadzieję, że będzie to prosta forma obiektu (# 3). Jeśli jednak szukasz jeszcze więcej opcji, możesz użyć dwóch tablic równolegle, jednej dla kluczy, a drugiej dla wartości; będzie on możliwie jak najbardziej kompaktowy, a jednocześnie będzie obsługiwał klucze obiektowe i klucze zduplikowane (które nie byłyby obsługiwane w # 3).
Erik Eidt

Odpowiedzi:

10

To, czy wybierzesz pierwszą, czy trzecią opcję, zależy od przypadku użycia. Jeśli modelujesz wiele różnych instancji tego samego rodzaju rzeczy, wybierz pierwszą. Na przykład masz listę osób. Jeśli modelujesz wiele różnych atrybutów jednej rzeczy, wybierz trzecią. Możesz mieć powtarzające się klucze w pierwszym formacie, ale nie w trzecim.

Druga opcja jest okropna i jeszcze nie znalazłem odpowiedniego dla niej przypadku użycia. Powodem, dla którego jest okropny, oprócz tego, że jest bardziej szczegółowy, jest to, że w przypadku JSON na jednym poziomie przerywa automatyczną konwersję większości bibliotek do słownika / mapy. W przypadku głęboko zagnieżdżonego JSON psuje interfejs zapytania podobny do XPath .

To sprawia, że ​​praca z nim jest trudna. A jeśli nie znasz swoich kluczy w czasie kompilacji, będziesz potrzebować słownika lub interfejsu XPath, ponieważ nie będziesz w stanie przekonwertować go na klasę. To może teraz nie wydawać się wielkim problemem, ale im dłużej masz format danych, tym trudniej będzie to zmienić.

Karl Bielefeldt
źródło
5
Dużą zaletą drugiej opcji jest to, że działa ona z kluczami nieciągłymi, w szczególności kluczami złożonymi.
CodesInChaos
1
Druga opcja jest okropna i musisz jeszcze znaleźć przypadek użycia? Tablica słowników z wieloma parami klucz / wartość musi dotyczyć najpopularniejszego formatu do przesyłania wielu obiektów.
gnasher729
2
@ gnasher729, w swojej „najczęściej format” sprawy prawdziwe przyciski są po lewej stronie: [{"key1": "value1", "key2": "value2"}]. Drugim formatem jest umieszczenie prawdziwego klucza po prawej stronie i użycie innego klucza o nazwie „Nazwa”, aby wskazać prawdziwy klucz, co sprawia, że ​​niezwykle trudno jest go sparsować za pomocą standardowych narzędzi.
Karl Bielefeldt,
Dam ci to, @CodesInChaos. Ale nawet tam musiałby to być wyjątkowy przypadek. Nigdy nie widziałem takiej potrzeby na wolności.
Karl Bielefeldt,
3
Przepraszam, ale to zła odpowiedź. Druga opcja jest zarówno bardzo często stosowana, jak i zalecana. Pozwala to na elastyczność kluczy, pozwala na rozszerzenie (o więcej pól wartości / metadanych) bez rozbijania konsumentów i może zachować kolejność elementów. Ponadto podane powody są fałszywe: nie przerywa żadnej „automatycznej konwersji” (jedynie szanuje prezentację autora jako tablicę) i działa dobrze z interfejsem zapytania podobnym do XPath. Jedynym minusem jest zwiększona gadatliwość.
Hejazzman
5

Trzeci format jest ogólnie najlepszy. Oto jednak przykład czegoś odpowiedniego dla 1. formatu:

[{
  "username": "foo",
  "id": 1
}, {
  "username": "bar",
  "id": 2
}, {
  "username": "baz",
  "id": 3
}]

Tutaj każdy obiekt odnosi się do osobnej rzeczy (a każdy obiekt używa tych samych kluczy, co inne, więc nie można ich scalić). Jednak każdy obiekt na liście jest przechowywany { "username": "foo", "id": 1 }raczej niż [{ "username": "foo" }, { "id": 1 }]dlatego, że 1) jest krótszy i 2) odnosi się do jednej rzeczy z nazwą użytkownika i identyfikatorem, a nie jednej rzeczy z nazwą użytkownika i innej rzeczy z identyfikatorem.

Problem z drugą opcją polega na tym, że staje się bardzo gadatliwy zarówno jako JSON, jak i do pracy. Można go jednak użyć, jeśli chcesz przechowywać meta-informacje o nieruchomości. Przykład:

{
  "key": "foo",
  "value": 1,
  "mutable": true
}

Tutaj mutableodnosi się do hipotetycznego przypadku, czy można zmodyfikować sama nieruchomość, a nie obiektu nadrzędnego. Takie meta-informacje są podobne do skryptów JavaScript Object.defineProperty, które przechowują informacje o właściwościach „konfigurowalne”, „wyliczalne” i „zapisywalne”.

gcampbell
źródło
Próbowałem użyć pierwszego formatu dla jakiegoś JSON, który wysyłałem do punktu końcowego C # REST i nie był on konwertowany na obiekt słownika. Konwersja go do trzeciego formatu rozwiązała ten problem.
fizch
5

Mówisz, że są to pary klucz / wartość. W takim przypadku użyj nr 3: słownik par klucz / wartość.

Jeśli nieto pary klucz / wartość, nie nazywaj ich „kluczami” i „wartościami” i użyj # 2, tablicy słowników z dowolną zawartością.

Struktura nr 1 jest po prostu głupia, chyba że potrzebujesz par klucz / wartość, ale także ich kolejności. Co rzadko robisz.

gnasher729
źródło
3

Postaw się w sytuacji osoby otrzymującej dżson. Jeśli nie znam nazwy klucza, jak mam ją odzyskać w pierwszym lub ostatnim formacie? Oczywiście możesz przełączyć przez JSON, ale ponieważ wszystkie trzy formaty osiągają ten sam wynik, to tylko kwestia składni. Myślę, że to jedyne znaczące pytanie: jeśli znasz nazwy kluczy, pierwsza lub ostatnia opcja jest bardziej zwarta, jeśli nie, drugi wybór jest bardziej zrozumiały.

JoulinRouge
źródło