Gibt es einen technischen Grund, warum nicht exportierte Felder von encoding / json nicht berücksichtigt werden? Wenn nicht und es ist eine willkürliche Entscheidung, könnte es eine zusätzliche Hintertüroption (sagen wir '+') geben, die aufgenommen werden kann, obwohl sie nicht exportiert wird?
Das Erfordernis des Client-Codes zum Exportieren, um diese Funktionalität zu erhalten, ist unglücklich, insbesondere wenn Kleinbuchstaben die Kapselung bereitstellen oder die Entscheidung, Strukturen zu marshallen, viel später als das Design dieser Strukturen erfolgt.
Wie gehen die Leute damit um? Einfach alles exportieren?
Wenn Sie keine Feldnamen exportieren, ist es auch schwierig, den vorgeschlagenen Redewendungen zu folgen. Ich denke, wenn eine Struktur X Feld Y hat, können Sie keine Zugriffsmethode Y () haben. Wenn Sie den Schnittstellenzugriff auf Y bereitstellen möchten, müssen Sie sich einen neuen Namen für den Getter einfallen lassen, und unabhängig davon, was Sie laut http://golang.org/doc/effective_go.html#Getters für etwas Unidiomatisches erhalten
UnmarshalJSON()
Methode vergessen . Ich habe das auch behoben.Field1
undField2
anwesend sind, da Godoc die nicht exportierte Struktur nicht auflisten würdejsonData
. Dieses Problem kann jedoch behoben werden, indem in der JsonData-Struktur kein anonymes Feld verwendet wird und ein nicht exportiertes benanntes Feld vorhanden ist. Dies erfordert dann , dassField1
undField2
werden durch den Namen, unexported Feld abgerufen. Ich habe die Antwort bearbeitet, um diese Methode zu verwenden.Stephens Antwort ist vollständig. Wenn Sie in Ihrem JSON nur Kleinbuchstaben benötigen, können Sie den Schlüsselnamen wie folgt manuell angeben:
type Whatever struct { SomeField int `json:"some_field"` }
Auf diese Weise erzeugt das Marshalling eines Whatever den Schlüssel "some_field" für das Feld SomeField (anstatt "SomeField" in Ihrem json zu haben).
Wenn Sie nicht exportierte Felder behalten möchten, können Sie auch die Schnittstelle json.Marshaler implementieren, indem Sie eine Methode mit der Signatur definieren
MarshalJSON() ([]byte, error)
. Eine Möglichkeit, dies zu tun, besteht darin, ein Strukturliteral zu verwenden, das einfach Versionen der nicht exportierten Felder exportiert hat, wie folgt:type Whatever struct { someField int } func (w Whatever) MarshalJSON() ([]byte, error) { return json.Marshal(struct{ SomeField int `json:"some_field"` }{ SomeField: w.someField, }) }
Das kann etwas umständlich sein, daher können Sie auch a verwenden,
map[string]interface{}
wenn Sie es vorziehen:func (w Whatever) MarshalJSON() ([]byte, error) { return json.Marshal(map[string]interface{}{ "some_field": w.SomeField, }) }
Es sollte jedoch beachtet werden, dass das Marshalling
interface{}
einige Einschränkungen aufweist und Dinge wie das Marschallierenuint64
eines Schwimmers bewirken kann, was zu einem Präzisionsverlust führt. (alles Code ungetestet)quelle
Die Verwendung einer Schnittstelle wäre eine weitere Option.
type Person interface { Name() string SetName(name string) Person Age() int SetAge(age int) Person } type person struct { Name_ string Age_ int } func (p *person) Name() string { return p.Name_ } func (p *person) SetName(name string) Person { p.Name_ = name return p } func (p *person) Age() int { return p.Age_ } func (p *person) SetAge(age int) Person { p.Age_ = age return p } func NewPerson() Person { return &person{} }
Da
person struct
es sich um Kleinbuchstaben handelt, können Sie außerhalb des Pakets nicht auf die öffentlichen Felder zugreifen. Um einen Personenwert zu instanziieren, geben Sie einen Konstruktor an, der ihn in Großbuchstaben zurückgibtPerson
.Spielplatz
quelle