json - 如何将具有动态字段的 JSON 对象映射到 Go 结构

标签 json go elasticsearch

我正在使用 Go 开发一个网站并将其连接到 Elastic Search。在 Elastic Search 中,我可以为索引类型设置动态字段。当我从 Elastic Search 读取文档时,它会返回一个 JSON 对象作为结果,其中可以包含具有动态名称的字段(或用户定义的字段)。

我可以获得 JSON 结果并将其解码为 Go 结构,但我不知道将这些动态字段保留为 Go 结构的一部分的最佳方法是什么。

这就是我正在做的。例如,如果我从 Elastic Search 获取联系人的文档,它可能看起来像这样:

{  
   "EmailAddress": "test@test.com",
   "Name": "Test Contact",
   "Phone": "17894785236",
   "City": "San Francisco",
   "State": "California"
}

Contact 的 Go 结构是:

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

我实现了MarshalerUnmarshaler覆盖对象的编码和解码方式。

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
}

这是最好的方法吗?你会推荐什么?

最佳答案

只需添加一点清理

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
        }
    }
}

关于json - 如何将具有动态字段的 JSON 对象映射到 Go 结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27492888/

相关文章:

php - 如何检查 mysql 表的 bool 字段以及在 php 中将 0 或 1 值转换为 true/false

javascript - 未捕获的类型错误 : Cannot call method 'request' of undefined

go - 多个作业有顺序吗?

elasticsearch - 在具有2GB RAM的计算机上引导elasticsearch

json - Golang 解码行为 : Excess fields?

java - 是否可以通过 GSON 将 ImageView 发送到另一个 Activity?

go - 在 golang 中,将 http 表单数据加载到结构中的通用函数

go - 导入包的正确项目结构

python - 使用 Python 对契约(Contract)桥接分数的 elasticsearch json 对象的元素进行计算

elasticsearch - 嵌套字段上的术语查询在 Elasticsearch 中不返回结果