在运行时确定结构时,JSON Unmarshal

时间:2016-10-20 04:51:11

标签: go

通常我们在Go中解组json对象:

我在Go中是一个菜鸟,所以请原谅我,如果下面的某些语法不正确。

//size2 has the size of the new array to be stored
store = realloc(store, size2 * sizeof int);

if (store == NULL)
{
   // Reallocation failed -- Take appropriate action
   printf ("Reallocation failed");
   exit(1);
}

现在抓住的是我的json在运行时可能会有所不同,具体取决于某些字段。价格可以是字符串,具有不同值的数组或包含一个对象中的货币和价格的json。

我在db中有这个映射,我怎么能编写我的代码,以便我读取列名到type的映射,然后解组它在运行时创建合适的struct。对于例如我需要在相同的代码中解组JSON: -

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的{"Quantity": 5, "Price": 64.5, "Currency": "USD"} {"Quantity": 5, "Purchase": {"Price": 64.5, "Currency": "USD"}} 映射。

TL;博士

需要根据一些参数解组运行时结构发生变化的json,并且我知道结构是否正确

修改:改写

我需要函数,它将返回上面struct的对象,将json字符串和json格式字符串作为输入。

Quantity -> int, Purchase -> JSON String

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

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

1 个答案:

答案 0 :(得分:1)

If your output structure and the keys in the input remain the same then it is possible to do what you require using the Unmarshaler interface.

type Unmarshaler interface {
        UnmarshalJSON([]byte) error
}

I've implemented a very crude, string only struct implimentation.

type Item struct {
    Quantity string `json:"quantity,omitempty"`
    Price    string `json:"price,omitempty"`
    Currency string `json:"currency,omitempty"`
}

Like I said it's very crude with a lot of assumptions and no checks in place.

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

Also note that the json tags you set for the structure represents how the json input keys should be, so keys like "Quantity" should be "quantity" in the JSON input, and so on.