I am developing a website using Go and connecting it to Elastic Search. In Elastic Search I can have dynamic fields for index types. When I read a document from Elastic Search it will return a JSON object as the result, which can include fields with dynamic names (or user defined fields).
I can get the JSON result and unmarshal it into a Go struct, but I do not know what is the best way to keep those dynamic fields as part of the Go struct.
This is what I am doing. For example, if I get a document for a Contact from Elastic Search it may look something like this:
{
"EmailAddress": "test@test.com",
"Name": "Test Contact",
"Phone": "17894785236",
"City": "San Francisco",
"State": "California"
}
And the Go struct for Contact is:
type Contact struct {
EmailAddress string
Name string
Phone string
CustomFields map[string]interface{}
}
And I implement Marshaler and Unmarshaler to override how the object is Marshaled and Unmarshalled.
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
}
Is this the best way to do this? What would you recommend?