通常我们在 Go 中解码一个 json 对象:
我是 Go 的菜鸟,所以如果下面的某些语法似乎不正确,请原谅我。
type Item struct {
Quantity int `json:"quantity,omitempty"`
Price float64 `json:"price,omitempty"`
Currency string `json:"currency,omitempty"`
}
output := &Item{}
err:= json.Unmarshal([]byte(data), output)
现在问题是我的 json 在运行时可能会因某些字段而异。价格可以是字符串、具有不同值的数组或在一个对象中包含货币和价格的 json。
我在数据库中有这个映射,我如何编写代码才能读取列名到类型的映射,然后解码它以在运行时创建合适的结构。例如我需要在同一代码中解码以下 JSON:-
{"Quantity": 5, "Price": 64.5, "Currency": "USD"}
{"Quantity": 5, "Purchase": {"Price": 64.5, "Currency": "USD"}}
对于数据库中的第二个 json,我已经有了像 Quantity -> int, Purchase -> JSON String
这样的映射。
tl;dr
需要解码 json,其中结构在运行时根据某些参数发生变化,我事先知道结构
编辑:改写
我需要一个函数,它会返回上面结构的对象,将 json 字符串和 json 格式字符串作为输入。
CustomUnmarshal([]byte(data) []byte, format string) (*item){}
我在这里写了一个示例代码:-
最佳答案
如果您的输出结构和输入中的键保持不变,则可以使用 Unmarshaler
接口(interface)执行您需要的操作。
type Unmarshaler interface {
UnmarshalJSON([]byte) error
}
我实现了一个非常粗糙的、只有字符串的结构实现。
type Item struct {
Quantity string `json:"quantity,omitempty"`
Price string `json:"price,omitempty"`
Currency string `json:"currency,omitempty"`
}
就像我说的那样,它非常粗糙,有很多假设并且没有检查到位。
func (itm *Item) UnmarshalJSON(byt []byte) (err error) {
jsn := string(byt)
jsn = strings.Replace(jsn,"{","",-1)
jsn = strings.Replace(jsn,"}","",-1)
jsnArr := strings.Split(jsn,":")
fmt.Println(jsnArr)
for i, val := range jsnArr {
switch {
case strings.Contains(val,"Quantity"):
itm.Quantity = strings.Split(jsnArr[i+1],",")[0]
case strings.Contains(val,"Price"):
itm.Price = strings.Split(jsnArr[i+1],",")[0]
case strings.Contains(val,"Currency"):
itm.Currency = strings.Split(jsnArr[i+1],",")[0]
}
}
return
}
另请注意,您为结构设置的 json 标记表示 json 输入键应该如何,所以像 "Quantity"
这样的键应该是 "quantity"
JSON 输入等。
关于go - 在运行时确定结构时进行 JSON Unmarshal,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40145706/