简体   繁体   English

将 json 数组解组为结构

[英]Unmarshal json array to struct

I have an array of custom values我有一组自定义值

[
    1,
    "test",
    { "a" : "b" }
]

I can unmarshal in to []interface{}, but it's not what I want.我可以解组到 []interface{},但这不是我想要的。

I would like to unmarshal this array to struct我想解组这个数组来构造

type MyType struct {
    Count int
    Name string
    Relation map[string]string
}

Is it possible in Go with standard or side libraries?在 Go 中是否可以使用标准库或侧库?

You can use github.com/ugorji/go/codec , it can unmarshal array to a struct:您可以使用github.com/ugorji/go/codec ,它可以将数组解组为结构:

Encode a struct as an array, and decode struct from an array in the data stream将结构体编码为数组,从数据流中的数组中解码结构体

Although the library advertises "drop-in replacement for encoding/json" - it's only about the json: tag.尽管该库宣传“编码/json 的直接替换” - 它仅与json:标签有关。 So you have to use codec.Decoder instead of json.Unmarshal :所以你必须使用codec.Decoder而不是json.Unmarshal

package main

import "fmt"
import "github.com/ugorji/go/codec"

type MyType struct {
    Count    int
    Name     string
    Relation map[string]string
}

func main() {
    x := &MyType{}
    data := []byte(`[1,"test",{"a":"b"}]`)
    codec.NewDecoderBytes(data, new(codec.JsonHandle)).Decode(x)
    fmt.Println(x)
}

The other answers seem too complicated, here is another approach:其他答案似乎太复杂了,这是另一种方法:

package main

import (
   "encoding/json"
   "fmt"
)

type myType struct {
   count int
   name string
   relation map[string]string
}

func (t *myType) UnmarshalJSON(b []byte) error {
   a := []interface{}{&t.count, &t.name, &t.relation}
   return json.Unmarshal(b, &a)
}

func main() {
   var t myType
   json.Unmarshal([]byte(`[1, "test", {"a": "b"}]`), &t)
   fmt.Printf("%+v\n", t)
}

https://eagain.net/articles/go-json-array-to-struct https://eagain.net/articles/go-json-array-to-struct

since your json holds values of different types in an array it is not possible to parse this with go simply.由于您的 json 在数组中包含不同类型的值,因此无法简单地用 go 解析它。 If you have controll over how the json input is formatted, wrap the three values in {} to form an object, like so:如果您可以控制 json 输入的格式,请将三个值包装在{}以形成一个对象,如下所示:

[
    {
        "Count": 1,
        "Name": "test",
        "Relation": { "a" : "b" }
     }
]

Then parsing into your struct should work.然后解析到你的结构应该工作。

If you have no controll over the json input.如果您无法控制 json 输入。 Parse it as []interface{} and then assign the values to your struct manually.将其解析为 []interface{},然后手动将值分配给您的结构。 Even though this might get tricky, depending on complexity of possible responses you'd like to support.即使这可能会变得棘手,这取决于您想要支持的可能响应的复杂性。

Please note, that this issue points to a core limitation of golangs json parsing method and that therefore - as far as I know - it can also not be solved by libraries.请注意,这个问题指向了 golangs json 解析方法的核心限制,因此 - 据我所知 - 它也无法通过库解决。

That is a tuple, and it's perfectly fine to unmarshal tuple into a structure, except that encoding/json doesn't support that.那是一个元组,将元组解组到一个结构中是完全没问题的,除了encoding/json不支持。

However we can use the following helper function, which iterates over the fields of the structure and unmarshals them:但是,我们可以使用以下辅助函数,它遍历结构的字段并解组它们:

// UnmarshalJSONTuple unmarshals JSON list (tuple) into a struct.
func UnmarshalJSONTuple(text []byte, obj interface{}) (err error) {
    var list []json.RawMessage
    err = json.Unmarshal(text, &list)
    if err != nil {
        return
    }

    objValue := reflect.ValueOf(obj).Elem()
    if len(list) > objValue.Type().NumField() {
        return fmt.Errorf("tuple has too many fields (%v) for %v",
            len(list), objValue.Type().Name())
    }

    for i, elemText := range list {
        err = json.Unmarshal(elemText, objValue.Field(i).Addr().Interface())
        if err != nil {
            return
        }
    }
    return
}

So you only need to provide the UnmarshalJSON method:所以你只需要提供UnmarshalJSON方法:

func (this *MyType) UnmarshalJSON(text []byte) (err error) {
    return UnmarshalJSONTuple(text, this)
}

Here is the complete example: http://play.golang.org/p/QVA-1ynn15这是完整的示例: http : //play.golang.org/p/QVA-1ynn15

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM