dongwu4834 2014-12-15 20:49
浏览 188

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

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?

  • 写回答

2条回答 默认 最新

  • doubian19900911 2014-12-15 22:08
    关注

    Just add little cleanup

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

报告相同问题?

悬赏问题

  • ¥30 win from 窗口最大最小化,控件放大缩小,闪烁问题
  • ¥20 易康econgnition精度验证
  • ¥15 msix packaging tool打包问题
  • ¥28 微信小程序开发页面布局没问题,真机调试的时候页面布局就乱了
  • ¥15 python的qt5界面
  • ¥15 无线电能传输系统MATLAB仿真问题
  • ¥50 如何用脚本实现输入法的热键设置
  • ¥20 我想使用一些网络协议或者部分协议也行,主要想实现类似于traceroute的一定步长内的路由拓扑功能
  • ¥30 深度学习,前后端连接
  • ¥15 孟德尔随机化结果不一致