有没有一种简单的方法可以通过 Golang 解码 JSON 数组中的不同对象?

huangapple go评论88阅读模式
英文:

Is there a simple way to decode different objects in an array of json by golang?

问题

一个 JSON 流描述了一个形状数组。这些形状可以是三角形、矩形或正方形。

例如:

{"shapes": [
	{"type": "triangle", "side1": 3, "side2": 4, "side3": 5},
	{"type": "rectangle", "width": 4, "height": 3},
	{"type": "square", "side": 3}
]}

这些结构在我的 Golang 代码中声明如下:

type Shape struct {
    Type string `json:"type"`
}

type Triangle struct {
    Shape
    Side1 int `json:"side1"`
    Side2 int `json:"side2"`
    Side3 int `json:"side3"`
}

type Rectangle struct {
    Shape
    Width  int `json:"width"`
    Height int `json:"height"`
}

type Square struct {
    Shape
    Side int `json:"side"`
}

我该如何将 JSON 解码为对象切片?非常感谢。

英文:

A json stream described an array of shapes. The shapes mayb be triangles, rectangles or squares.

For example:

{"shapes": [
	{"type": "triangle", "side1": 3, "side2": 4, "side3": 5},
	{"type": "rectangle", "width": 4, "height": 3},
	{"type": "square", "side": 3}
]}

These structures are declared in my golang code:

type Shape struct {
    Type string `json:"type"`
}

type Triangle struct {
    Shape
    Side1 int `json:"side1"`
    Side2 int `json:"side2"`
    Side3 int `json:"side3"`
}

type Rectangle struct {
    Shape
    Width  int `json:"width"`
    Height int `json:"height"`
}

type Square struct {
    Shape
    Side int `json:"side"`
}

How can I decode the json into an object slice? Thank you very much.

答案1

得分: 1

创建一个新的类型Shapes来解析shapes,并实现自定义的UnmarshalJSON方法来解析Shapes

type Shapes struct {
	Shapes []interface{} `json:"shapes"`
}

func (b *Shapes) UnmarshalJSON(data []byte) error {

	var v = struct {
		Shapes []map[string]interface{} `json:"shapes"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	types := make([]interface{}, 0)

	for _, shape := range v.Shapes {
		shp := Shape{Type: shape["type"].(string)}
		switch shp.Type {
		case "triangle":
			typ := Triangle{
				Shape: shp,
				Side1: int(shape["side1"].(float64)),
				Side2: int(shape["side2"].(float64)),
				Side3: int(shape["side3"].(float64)),
			}
			types = append(types, typ)
		case "rectangle":
			typ := Rectangle{
				Shape:  shp,
				Width:  int(shape["width"].(float64)),
				Height: int(shape["height"].(float64)),
			}
			types = append(types, typ)
		case "square":
			typ := Square{
				Shape: shp,
				Side:  int(shape["side"].(float64)),
			}
			types = append(types, typ)
		}
	}

	b.Shapes = types

	return nil
}

将json字符串解析为Shapes类型。你可以在Shapes.Shapes数组中访问你的形状类型。

func main() {
	jStr := `{"shapes": [
    {"type": "triangle", "side1": 3, "side2": 4, "side3": 5},
    {"type": "rectangle", "width": 4, "height": 3},
    {"type": "square", "side": 3}
]}`

	shapes := Shapes{}
	err := json.Unmarshal([]byte(jStr), &shapes)
	if err != nil {
		panic(err)
	}
	fmt.Println(shapes)
}

完整代码请参考这里

英文:

Create new type Shapesto unmarshal shapes and implement your custom UnmarshalJSON to Shapes

type Shapes struct {
	Shapes []interface{} `json:"shapes"`
}

func (b *Shapes) UnmarshalJSON(data []byte) error {

	var v = struct {
		Shapes []map[string]interface{} `json:"shapes"`
	}{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}
	types := make([]interface{}, 0)

	for _, shape := range v.Shapes {
		shp := Shape{Type: shape[`type`].(string)}
		switch shp.Typ() {
		case `triangle`:
			typ := Triangle{
				Shape:shp,
				Side1: int(shape[`side1`].(float64)),
				Side2: int(shape[`side2`].(float64)),
				Side3: int(shape[`side3`].(float64)),
			}
			types = append(types, typ)
		case `rectangle`:
			typ := Rectangle{
				Shape:  shp,
				Width:  int(shape[`width`].(float64)),
				Height: int(shape[`height`].(float64)),
			}
			types = append(types, typ)
		case `square`:
			typ := Square{
				Shape:  shp,
				Side:  int(shape[`side`].(float64)),
			}
			types = append(types, typ)
		}
	}

	b.Shapes = types

	return nil
}

Unmarshal json string to Shapes type. You can access your shape types in Shapes.Shapes array.

func main() {
	jStr := `{"shapes": [
    {"type": "triangle", "side1": 3, "side2": 4, "side3": 5},
    {"type": "rectangle", "width": 4, "height": 3},
    {"type": "square", "side": 3}
]}`

	shapes := Shapes{}
	err := json.Unmarshal([]byte(jStr), &shapes)
	if err != nil {
		panic(err)
	}
	fmt.Println(shapes)
}

Find full code here

huangapple
  • 本文由 发表于 2021年6月12日 12:29:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/67945617.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定