JSON i radzenie sobie z nieuregulowanymi polami

Czy jest jakiś techniczny powód, dla którego pola nie są dołączane przez encoding / json? Jeśli nie i jest to arbitralna decyzja, czy może istnieć dodatkowa opcja tylnych drzwi (powiedzmy"+") do włączenia, nawet jeśli nie jest to możliwe?

Wymaganie eksportu kodu klienta w celu uzyskania tej funkcjonalności wydaje się niefortunne, zwłaszcza jeśli małe litery zapewniają enkapsulację lub decyzja o budowie jest znacznie późniejsza niż ich zaprojektowanie.

Jak ludzie sobie z tym radzą? Po prostu Eksportuj wszystko?

Również, czy eksportowanie nazw pól nie utrudnia podążania za sugerowanymi idiomami. Myślę, że jeśli struktura X ma pole Y, nie można mieć metody accessor Y (). Jeśli chcesz zapewnić dostęp do interfejsu Y, musisz wymyślić nową nazwę dla gettera i bez względu na to, co dostaniesz coś nie-idiomatycznego zgodnie z http://golang.org/doc/effective_go.html#Getters

 49
Author: Flimzy, 2012-06-20

2 answers

Jest powód techniczny. Biblioteka json nie ma możliwości wyświetlania pól za pomocą reflect, chyba że zostaną wyeksportowane. Pakiet może przeglądać tylko niezaksięgowane pola typów w ramach własnego pakietu

Aby poradzić sobie z Twoim problemem, możesz stworzyć Typ niewyeksportowany z wyeksportowanymi polami. Json będzie unmarshal do typu unexported, jeśli zostanie do niego przekazany bez problemu, ale nie pojawi się w dokumentach API. Następnie można utworzyć wyeksportowany typ, który osadza / align = "left" / Ten wyeksportowany Typ będzie potrzebował metod do implementacji interfejsów json.Marshaler i json.Unmarshaler.

Uwaga: cały kod nie jest testowany i może nawet nie być kompilowany.

type jsonData struct {
    Field1 string
    Field2 string
}

type JsonData struct {
    jsonData
}

// Implement json.Unmarshaller
func (d *JsonData) UnmarshalJSON(b []byte) error {
    return json.Unmarshal(b, &d.jsonData)
}

// Getter
func (d *JsonData) Field1() string {
    return d.jsonData.Field1
}
 77
Author: Stephen Weinberg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-29 07:54:01

Odpowiedź Stephena jest kompletna. Na marginesie, jeśli wszystko, co naprawdę chcesz, to małe litery w json, możesz ręcznie podać nazwę klucza w następujący sposób:

type Whatever struct {
    SomeField int `json:"some_field"`
}

W ten sposób, marshaling a Whatever tworzy klucz "some_field" dla pola SomeField(zamiast "SomeField" w Twoim json).

Jeśli nie jesteś nastawiony na utrzymywanie nieprzeznaczonych pól, możesz również zaimplementować json.Interfejs marshalera poprzez zdefiniowanie metody z podpisem MarshalJSON() ([]byte, error). Jednym ze sposobów jest użycie literał struktury, który po prostu wyeksportował wersje nieeksportowanych pól, Jak to:

type Whatever struct {
    someField int
}

func (w Whatever) MarshalJSON() ([]byte, error) {
    return json.Marshal(struct{
        SomeField int `json:"some_field"`
    }{
        SomeField: w.someField,
    })
}

To może być trochę uciążliwe, więc możesz również użyć map[string]interface{} jeśli wolisz:

func (w Whatever) MarshalJSON() ([]byte, error) {
    return json.Marshal(map[string]interface{}{
        "some_field": w.SomeField,
    })
}

Należy jednak zauważyć, że marshaling interface{} ma pewne zastrzeżenia i może wykonywać rzeczy takie jak marshal uint64 na pływaku, powodując utratę precyzji. (all code untested)

 48
Author: jorelli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-28 19:41:25