Inkonsistente JSON-Feldverarbeitung: Unmarshaling als String oder Array
Bei der Arbeit mit JSON-Daten, die Inkonsistenzen aufweisen, kann das Unmarshaling eine Herausforderung darstellen Felder, deren Typ variieren kann, z. B. entweder eine Zeichenfolge oder ein Array von Zeichenfolgen. Dieser Artikel befasst sich mit diesem Problem und bietet praktische Lösungen.
Das Problem
Betrachten Sie die folgende JSON-Struktur, bei der das Feld „display_name“ entweder eine Zeichenfolge oder ein Array von Zeichenfolgen ist :
{ "date": "30 Apr", "display_name": "Mr Smith" }, { "date": "30 Apr", "display_name": ["Mr Smith", "Mr Jones"], }
Der Versuch, diese Daten mit den folgenden Go-Strukturen zu entmarshalieren, führt zu einem Fehler:
type MyListItem struct { Date string `json:"date"` DisplayName string `json:"display_name"` } type MyListings struct { CLItems []MyListItem `json:"myitems"` }
Lösung
Um diese Herausforderung zu meistern, kann man die Vielseitigkeit von json.RawMessage nutzen, das die Erfassung unterschiedlicher Felddaten ermöglicht. Darüber hinaus kann der Feldname „-“ verwendet werden, um das Feld „DisplayName“ vor dem Decoder auszublenden, sodass die Anwendung es füllen kann, nachdem der JSON der obersten Ebene dekodiert wurde.
Geänderte Go-Struktur
type MyListItem struct { Date string `json:"date"` RawDisplayName json.RawMessage `json:"display_name"` DisplayName []string `json:"-"` }
Unmarshaling-Prozess
Unmarshaling der JSON der obersten Ebene:
var li MyListItem if err := json.Unmarshal(data, &li); err != nil { // handle error }
Rekonstruktion des Felds „display_name“ basierend auf dem Typ der Rohdaten:
if len(li.RawDisplayName) > 0 { switch li.RawDisplayName[0] { case '"': if err := json.Unmarshal(li.RawDisplayName, &li.DisplayName); err != nil { // handle error } case '[': var s []string if err := json.Unmarshal(li.RawDisplayName, &s); err != nil { // handle error } // Join arrays with "&&" per OP's comment on the question. li.DisplayName = strings.Join(s, "&&") } }
Bei mehreren Vorkommen dieses inkonsistenten Felds innerhalb eines Datenmodells a Benutzerdefinierter Typ und Implementierung der json.Unmarshaler-Schnittstelle können verwendet werden, um die Logik zu kapseln.
Benutzerdefiniert Unmarshaler
type multiString string func (ms *multiString) UnmarshalJSON(data []byte) error { if len(data) > 0 { switch data[0] { case '"': var s string if err := json.Unmarshal(data, &s); err != nil { return err } *ms = multiString(s) case '[': var s []string if err := json.Unmarshal(data, &s); err != nil { return err } *ms = multiString(strings.Join(s, "&&")) } } return nil }
Verwendung mit benutzerdefiniertem Unmarshaler
type MyListItem struct { Date string `json:"date"` DisplayName multiString `json:"display_name"` } type MyListings struct { CLItems []MyListItem `json:"myitems"` } var listings MyListings if err := json.Unmarshal([]byte(data), &listings); err != nil { log.Fatal(err) }
Diese Lösungen bieten einen umfassenden Ansatz zur effizienten Handhabung inkonsistenter JSON-Felder und ermöglichen eine flexible Zuordnung zwischen Datenstrukturen und JSON-Darstellungen.
Das obige ist der detaillierte Inhalt vonWie kann ich inkonsistente JSON-Felder, die manchmal Strings und manchmal Arrays von Strings sind, in Go effizient entmarshalieren?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!