2014-12-15 9 views
7

Ich entwickle eine Website mit Go und verbinde sie mit Elastic Search. In der elastischen Suche kann ich dynamische Felder für Indextypen haben. Wenn ich ein Dokument aus Elastic Search lese, wird ein JSON-Objekt als Ergebnis zurückgegeben, das Felder mit dynamischen Namen (oder benutzerdefinierten Feldern) enthalten kann.So ordnen Sie JSON-Objekte mit dynamischen Feldern zu Go-Strukturen an

Ich kann das JSON-Ergebnis abrufen und es in eine Go-Struktur entpacken, aber ich weiß nicht, was der beste Weg ist, diese dynamischen Felder als Teil der Go-Struktur zu behalten.

Das ist, was ich tue. Zum Beispiel, wenn ich ein Dokument für einen Kontakt aus Elastic erhalten Suchen es so etwas wie folgt aussehen:

{ 
    "EmailAddress": "[email protected]", 
    "Name": "Test Contact", 
    "Phone": "17894785236", 
    "City": "San Francisco", 
    "State": "California" 
} 

Und die Go-Struktur für Kontaktaufnahme:

type Contact struct { 
    EmailAddress   string 
    Name     string 
    Phone     string 
    CustomFields   map[string]interface{} 
} 

Und ich implementieren Marshaler und Unmarshaler zu überschreiben, wie das Objekt Marshalled und Unmarshalled ist.

func (c *Contact) MarshalJSON() ([]byte, error) { 
    contactMap := make(map[string]interface{}) 
    contactMap["EmailAddress"] = c.EmailAddress 
    contactMap["Name"] = c.Name 
    contactMap["Phone"] = c.Phone 

    for k, v := range c.CustomFields { 
     contactMap[k] = v 
    } 

    return json.Marshal(contactMap) 
} 

func (c *Contact) UnmarshalJSON(data []byte) error { 
    var contactMap map[string]interface{} 

    if c == nil { 
     return errors.New("RawString: UnmarshalJSON on nil pointer") 
    } 

    if err := json.Unmarshal(data, &contactMap); err != nil { 
     return err 
    } 

    c.EmailAddress = contactMap["EmailAddress"].(string) 
    c.Name = contactMap["Name"].(string) 
    c.Phone = contactMap["Phone"].(string) 

    for key, val := range contactMap { 
     if key != "EmailAddress" && key != "Name" && Key != "Phone" { 
      c.CustomFields[key] = value 
     } 
    } 

    return nil 
} 

Ist dies der beste Weg, dies zu tun? Was würden Sie empfehlen?

+1

Wie zufällig werden die Felder sein? Möglicherweise völlig zufällig? Wenn ja, ist das, was Sie oben haben, Ihre beste Wette. Wenn Sie jedoch die dynamischen Teile auf eine bestimmte Struktur beschränken können, können Sie weitere Strukturen um diesen Teil herum modellieren und sie getrennt entpacken, nachdem Sie festgestellt haben, was sie sind. –

+0

Ja, sie werden zufällig sein. Sie folgen keiner Struktur, sie sind benutzerdefinierte Felder. Ich werde es so lassen wie es ist. – user1845791

Antwort

3

Nur wenig Bereinigungs

var contactMap map[string]interface{} 

if c == nil { 
    return errors.New("RawString: UnmarshalJSON on nil pointer") 
} 

if err := json.Unmarshal(data, &contactMap); err != nil { 
    return err 
} 

for key, val := range contactMap { 
    switch key { 
     case "EmailAddress": 
      c.EmailAddress = val.(string) 
     case "Name": 
      c.Name = val.(string) 
     case "Phone": 
      c.Phone = val.(string) 
     default: 
      c.CustomFields[key] = val 
     } 
    } 
} 
+0

Danke. Ich werde diese Änderung vornehmen. – user1845791

+0

Gern geschehen. –

4

hinzufügen Als Simon in Kommentar hervorgehoben hat, eine große map [string] Schnittstelle mit {}, wenn die Struktur des json nicht ideal ist festgelegt ist. Der beste Weg ist dann, die Struktur zu verwenden und sie mit http://golang.org/pkg/encoding/json/#Unmarshal zu entfernen. (siehe das Beispiel: http://play.golang.org/p/cDTe8x4xLk)

Aber für große Json Blob, für die Struktur nicht im Voraus bekannt ist, funktioniert Ihre Implementierung perfekt.

bearbeiten: Link zum Beispiel hinzugefügt

Verwandte Themen