Płaski czy zagnieżdżony JSON dla danych hierarchicznych?

12

Zmieniałem już ~ 5 razy. Ten punkt końcowy REST /api/tags/będzie do użytku wewnętrznego (bez klientów innych firm), jestem jedynym, który z nim pracuje.

Decyduję między tymi dwoma reprezentacjami:

Mieszkanie

{  
   "types":[  
      {  
         "id":1,
         "text":"Utility"
      },
      {  
         "id":7,
         "text":"Lease Terms"
      },
   ],
   "tags":[
      {  
         "id":8,
         "text":"Water",
         "type":1
      },
      {  
         "id":9,
         "text":"Electricity",
         "type":1
      },
      {  
         "id":5,
         "text":"Minimum 12 month lease",
         "type":7
      },
      {  
         "id":17,
         "text":"lease negotiable/flexible",
         "type":7
      },
   ]
}
  • Jest nieco modułowy. Można dodać kolejną górną warstwę, na przykład „kraj”, bez naruszania zgodności.

Zagnieżdżone

{  
   "1":{  
      "text":"Utility",
      "tags":{  
         "8":{  
            "text":"Water"
         },
         "9":{  
            "text":"Electricity"
         },
      }
   },
   "2":{  
      "text":"Lease Terms",
      "tags":{  
         "5":{  
            "text":"Minimum 12 month lease"
         },
         "17":{  
            "text":"lease negotiable/flexible"
         },
      }
   },
}
  • Jest już w użytecznym formacie. Nie musisz zapętlać danych przed ich użyciem.
  • Oszczędza trochę przepustowości. Nawet po gzipie jest on nieco mniejszy.

Którego należy użyć i dlaczego? Jeśli jest to kwestia osobistych preferencji, jaką reprezentację woleliby doświadczeni programiści i dlaczego?

dvtan
źródło
Is this a matter of personal preference?. Chyba tak. Wymagania> potrzeby> preferencje
Laiv
1
@Laiv W takim przypadku moje pytanie należy przeformułować „Jaką reprezentację preferują doświadczeni programiści i dlaczego?”
dvtan
Czy te identyfikatory są stabilne w czasie i czy klient może je zapamiętać i wykorzystać później, czy też są tylko lokalnymi wiadomościami?
Erik Eidt,
@ErikEidt Są to stałe klucze podstawowe bazy danych.
dvtan
Czy traktujesz wodę bardziej jako podklasę Utility, czy bardziej jako instancję Utility?
Erik Eidt,

Odpowiedzi:

8

Zależy od twojego przypadku użycia.

Podczas korzystania z JSON z językami typowymi dla statiki istnieje ogromna premia, jeśli twoja struktura jest odwzorowana na typy. Oznacza to, że wszystkie nazwy kluczy powinny być znane z góry.

Tak więc, jeśli planujesz używać Javy do korzystania z usługi lub jeśli planujesz ją udokumentować za pomocą schematu JSON, numer jeden będzie znacznie czystszy (oczywiście oba będą działać).

fdreger
źródło
4

Trudno powiedzieć bez większego kontekstu. Pracowałem z obydwoma, ale stopniowo zacząłem skłaniać się do # 1. Ogólnie rzecz biorąc, prostota jest dla mnie ważniejsza niż wyrafinowanie.

W # 1 byty i relacje są jasne i oczywiste, podczas gdy # 2 wymaga innego sposobu myślenia. Dla niektórych osób drzewa (jako struktury danych) nie są tak samoopisowe. Pomyśl o młodszych programistach, którzy ledwo widzieli agregację kompozycji | głębszą niż Osoba> Adres .

Mogłem przeczytać nr 1 jako:

  • istnieje kolekcja wpisanych tagów .

Ale jak moglibyśmy opisać # 2 tylko w 7 słowach? Gdybym nie był zaznajomiony ze strukturami drzew, mógłbym odczytać # 2 jako

  • tagi mają dwa atrybuty 5 i 17, ale nie znam ich typów. Niezależnie od typu, ma jeden atrybut, tekst .

Nie zrozumcie mnie źle, # 2 może być inteligentnym rozwiązaniem, ale nie poświęciłbym niepotrzebnie czytelności (lub wydajności).

Pisząc tę ​​odpowiedź, pracuję nad projektem, który musi zostać zintegrowany z zewnętrzną usługą, której odpowiedzi są bardzo podobne do # 2. Usługa zapewnia nam kalendarz: rok, miesiące, dni i godziny dnia

 { "2017" : { "01": { "01" : ["00:00", "01:00", "02:00"] } } } 

Jako programista Java jestem, deserializacja odpowiedzi usługi zakończyła się kodem, który nie jest czytelny, ponieważ nie ma bezpośredniego mapowania na klasy za pomocą konstruktorów getters | setters | Zamiast tego musiałem przejrzeć dokument ( getNode, getSiblings, getNodeName, getChildAsText, isNodeObject, isText itp.) I ręcznie zapełnić moją hierarchię klas. W końcu udało mi się zamapować drzewo liczb na zbiór znaczników czasu! Którą strukturę według ciebie jest łatwiejsza do odczytania i deserializacji? A który chciałbyś dostać, gdybyś był po stronie klienta?

Laiv
źródło
1

Jeśli nie chcesz niczego więcej, możesz po prostu użyć:

{
    "Utility": {
        "8": "Water",
        "9": "Electricity"
     },
     "Lease Terms": {
        "5": "Minimum 12 month lease",
        "17": "lease negotiable/flexible"
     }
}

Niestety, JSON dopuszcza tylko ciągi jako klucze.

gnasher729
źródło
Lub potencjalnie "Utility": ["Water","Electricity"]itp.
Caleth
Ale nie możesz ich odwoływać. Spodziewałbym się, że za tym wszystkim pojawi się tablica opisująca tysiące domów, z których każda zawiera na przykład „8”, „9”, „5”.
gnasher729