go - 在运行时确定结构时进行 JSON Unmarshal

标签 go

通常我们在 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){}

我在这里写了一个示例代码:-

https://play.golang.org/p/JadYOnBQne

最佳答案

如果您的输出结构和输入中的键保持不变,则可以使用 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
}

Full Program

另请注意,您为结构设置的 json 标记表示 json 输入键应该如何,所以像 "Quantity" 这样的键应该是 "quantity" JSON 输入等。

关于go - 在运行时确定结构时进行 JSON Unmarshal,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40145706/

相关文章:

go - 通过 import 生成基于 protobuf 的 go 文件

php - 从相对路径解析绝​​对路径

go - AppEngine 部署找不到 Go 包

shell - 在同一个 shell golang 中运行多个 Exec 命令

mongodb - Mongodb 中的投影无法正常工作

go - 函数声明语法 : things in parenthesis before function name

string - 如何在 Golang 中将数字转换为 1=A1, 2=A2, ... 9=B1, ... 64=H8 形式的字符串?

go - 使用事务进行 sqlite 查询?

go - 如何使用 graphql-go 发出请求

go - 如何在 GoLand 的虚拟环境中运行 file watcher?