Stworzyłem API w Go, które po wywołaniu wykonuje zapytanie, tworzy instancję struktury, a następnie koduje tę strukturę jako JSON przed wysłaniem z powrotem do dzwoniącego. Chciałbym teraz pozwolić wywołującemu na wybranie określonych pól, które chcieliby zwrócić, przekazując parametr GET „pola”.
Oznacza to, że w zależności od wartości pól moja struktura uległaby zmianie. Czy istnieje sposób na usunięcie pól ze struktury? Lub przynajmniej dynamicznie ukryć je w odpowiedzi JSON? (Uwaga: czasami mam puste wartości, więc tag JSON omitEmpty nie będzie działał w tym miejscu). Jeśli żadne z powyższych nie jest możliwe, czy istnieje sugestia dotycząca lepszego sposobu rozwiązania tego problemu? Z góry dziękuję.
Poniżej znajduje się mniejsza wersja struktur, których używam:
type SearchResult struct {
Date string `json:"date"`
IdCompany int `json:"idCompany"`
Company string `json:"company"`
IdIndustry interface{} `json:"idIndustry"`
Industry string `json:"industry"`
IdContinent interface{} `json:"idContinent"`
Continent string `json:"continent"`
IdCountry interface{} `json:"idCountry"`
Country string `json:"country"`
IdState interface{} `json:"idState"`
State string `json:"state"`
IdCity interface{} `json:"idCity"`
City string `json:"city"`
} //SearchResult
type SearchResults struct {
NumberResults int `json:"numberResults"`
Results []SearchResult `json:"results"`
} //type SearchResults
Następnie koduję i wyprowadzam odpowiedź w następujący sposób:
err := json.NewEncoder(c.ResponseWriter).Encode(&msg)
Odpowiedzi:
EDYCJA: Zauważyłem kilka głosów przeciw i ponownie przyjrzałem się temu pytaniu i odpowiedziom. Większość ludzi wydaje się nie zauważyć, że program operacyjny poprosił o dynamiczne wybieranie pól na podstawie listy pól dostarczonej przez dzwoniącego. Nie możesz tego zrobić za pomocą statycznie zdefiniowanego tagu struct json.
Jeśli chcesz zawsze pomijać pole do kodowania json, użyj oczywiście
json:"-"
do zignorowania pola (pamiętaj również, że nie jest to wymagane, jeśli twoje pole nie jest eksportowane - te pola są zawsze ignorowane przez koder json). Ale to nie jest pytanie PO.Cytując komentarz do
json:"-"
odpowiedzi:W tym przypadku użyłbym map [string] interface {} zamiast struktury. Możesz łatwo usunąć pola, wywołując
delete
wbudowane na mapie pola do usunięcia.Oznacza to, że jeśli nie możesz zapytać tylko o żądane pola w pierwszej kolejności.
źródło
map[string]interface{}
ma sens, ale nie wymaga odrzucania definicji typu.Id
ale nie chcę zwracać całej struktury json. Dzięki za to!użyj `json:" - "`
doc: http://golang.org/pkg/encoding/json/#Marshal
źródło
Innym sposobem na zrobienie tego jest utworzenie struktury wskaźników ze
,omitempty
znacznikiem. Jeśli wskaźniki są zerowe , pola nie zostaną uporządkowane.Ta metoda nie będzie wymagała dodatkowej refleksji ani nieefektywnego wykorzystania map.
Ten sam przykład co jorelli przy użyciu tej metody: http://play.golang.org/p/JJNa0m2_nw
źródło
Możesz użyć
reflect
pakietu, aby wybrać żądane pola, odzwierciedlając znaczniki pól i wybierającjson
wartości znaczników. Zdefiniować metodę na swoim searchresults typ, który wybiera pola i zwraca je wmap[string]interface{}
, a następnie zebrać że zamiast się SearchResults struct się. Oto przykład, jak możesz zdefiniować tę metodę:a oto gotowe do uruchomienia rozwiązanie, które pokazuje, jak wywołać tę metodę i zorganizować wybór: http://play.golang.org/p/1K9xjQRnO8
źródło
Właśnie opublikowałem szeryfa , który przekształca struktury w mapę na podstawie tagów z adnotacjami w polach struktury. Następnie możesz zorganizować (JSON lub inne) wygenerowaną mapę. Prawdopodobnie nie pozwala ci tylko na serializację zestawu pól, o które prosił dzwoniący, ale wyobrażam sobie, że użycie zestawu grup pozwoliłoby ci objąć większość przypadków. Użycie grup zamiast pól bezpośrednio prawdopodobnie również zwiększyłoby pojemność pamięci podręcznej.
Przykład:
źródło
Weź trzy składniki:
reflect
Pakiet do pętli na wszystkich polach struct.if
Oświadczenie odebrać pola, które chceszMarshal
, aencoding/json
PakietMarshal
dziedzinach własnych upodobań.Przygotowanie:
Wymieszaj je w dobrej proporcji. Użyj,
reflect.TypeOf(your_struct).Field(i).Name()
aby uzyskać nazwęi
tego polayour_struct
.Służy
reflect.ValueOf(your_struct).Field(i)
do uzyskiwaniaValue
reprezentacji typu dlai
th polayour_struct
.Służy
fieldValue.Interface()
do pobierania rzeczywistej wartości (przesłanej do typu interfejs {})fieldValue
typuValue
(zwróć uwagę na użycie nawiasu - metoda Interface () dajeinterface{}
Jeśli na szczęście uda ci się nie spalić żadnych tranzystorów lub wyłączników w procesie, powinieneś dostać coś takiego:
Porcja:
na przykład służyć z dowolną strukturą i
map[string]bool
polami, które chcesz uwzględnićSmacznego!
źródło
Możesz użyć atrybutu tagowania „omitifempty” lub utworzyć wskaźniki do pól opcjonalnych i pozostawić te, które chcesz pominąć, niezainicjalizowane.
źródło
Też napotkałem ten problem, na początku chciałem tylko wyspecjalizować odpowiedzi w moim module obsługi http. Moje pierwsze podejście polegało na utworzeniu pakietu, który kopiuje informacje o strukturze do innej struktury, a następnie organizuje tę drugą strukturę. Zrobiłem ten pakiet używając refleksji, więc nigdy nie podobało mi się to podejście, a także nie byłem dynamiczny.
Postanowiłem więc zmodyfikować pakiet encoding / json, aby to zrobić. Funkcje
Marshal
,MarshalIndent
a(Encoder) Encode
dodatkowo otrzymuje pliktype F map[string]F
Chciałem zasymulować JSON pól, które są potrzebne do organizowania, więc porządkuje tylko te pola, które są na mapie.
https://github.com/JuanTorr/jsont
źródło
Pytanie jest teraz trochę stare, ale chwilę temu natknąłem się na ten sam problem, a ponieważ nie znalazłem łatwego sposobu, aby to zrobić, zbudowałem bibliotekę spełniającą ten cel. Pozwala w łatwy sposób wygenerować a
map[string]interface{}
ze struktury statycznej.https://github.com/tuvistavie/structomap
źródło
[]byte
jest to, że nie nadaje się on do ponownego wykorzystania: na przykład nie ma łatwego sposobu na późniejsze dodanie pola. Dlatego sugerowałbym utworzeniemap[string]interface{}
i pozwolenie części serializacji JSON na standardową bibliotekę.Nie miałem tego samego problemu, ale podobny. Poniższy kod rozwiązuje również Twój problem, oczywiście jeśli nie masz nic przeciwko problemowi z wydajnością. Przed wdrożeniem tego typu rozwiązania w swoim systemie, polecam przeprojektowanie struktury, jeśli masz taką możliwość. Wysyłanie odpowiedzi o zmiennej strukturze jest przesadą techniczną. Uważam, że struktura odpowiedzi reprezentuje kontrakt między żądaniem a zasobem i nie powinno to być żądaniami zależnymi (można ustawić niepotrzebne pola na wartość null, tak jest). W niektórych przypadkach musimy wdrożyć ten projekt, jeśli uważasz, że tak jest, oto link do gry i kod, którego używam.
źródło
Stworzyłem tę funkcję, aby przekonwertować struct na ciąg JSON, ignorując niektóre pola. Mam nadzieję, że to pomoże.
Przykład: https://play.golang.org/p/nmq7MFF47Gp
źródło