我正在使用Go开发一个网站并将其连接到Elastic Search。在弹性搜索中,我可以为索引类型提供动态字段。当我从Elastic Search读取文档时,它将返回一个JSON对象作为结果,其中可以包含具有动态名称(或用户定义的字段)的字段。
我可以获取JSON结果并将其解组为Go结构,但我不知道将这些动态字段保留为Go结构的一部分的最佳方法是什么。
这就是我在做的事情。例如,如果我从Elastic Search获得联系人的文档,它可能看起来像这样:
{
"EmailAddress": "test@test.com",
"Name": "Test Contact",
"Phone": "17894785236",
"City": "San Francisco",
"State": "California"
}
联系人的Go结构是:
type Contact struct {
EmailAddress string
Name string
Phone string
CustomFields map[string]interface{}
}
我实施Marshaler和Unmarshaler来覆盖对象的编组和解组的方式。
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
}
这是最好的方法吗?你会推荐什么?
答案 0 :(得分:4)
正如西蒙在评论中指出的那样,如果json的结构是固定的,那么使用一个大的 map [string] interface {} 是不理想的。最好的方法是使用结构并使用http://golang.org/pkg/encoding/json/#Unmarshal解组它。 (参考示例:http://play.golang.org/p/cDTe8x4xLk)
但对于大型json blob,预先知道哪种结构,您的实现工作正常。
编辑:添加了示例
的链接答案 1 :(得分:3)
添加一点清理
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
}
}
}