将一个对象转换为对象数组(JSON)在Go中。

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

Convert an object to an array of objects (JSON) in Go

问题

我正在将一个 JS API 转换为 Go。我使用来自第三方的数据,有时属性是一个包含各种键值对的对象,而不是对象数组(键值对的对象数组)。

因此,在我的前端中,如果它是一个对象,它就不会被渲染,所以我将其转换为对象数组。

目前在 JS 中,我这样做:

if (!Array.isArray(data.attributes)) {
      // convert into array of objects; only works for non separate key:key value:value
      data.attributes = Object.entries(data.attributes).map(
        ([key, value]) => ({
          type: key,
          value: value,
        })
      );
    }

data 是 JSON 响应中的一个属性,例如:
{... data: { "attributes": [{...}{...}]}

因此,偶尔属性会是 {... data: { "attributes": {name: "John", age: "20" }

在 Go 中,我该如何做类似的操作?谢谢。

英文:

I am converting a JS API to Go. I use data from a third party where sometimes a property is an object of various key, value rather than an array of objects (of key, value).

So in my frontend if it's an object it won't render so I convert it into an array of objects.

Currently in JS I'm doing this:

if (!Array.isArray(data.attributes)) {
      // convert into array of objects; only works for non separate key:key value:value
      data.attributes = Object.entries(data.attributes).map(
        ([key, value]) => ({
          type: key,
          value: value,
        })
      );
    }

data is a property in a JSON response like:
{... data: { "attributes": [{...}{...}]}

So occasionally attributes will be {... data: { "attributes": {name: "John", age: "20" }:

How would I do something like this in Go? Thanks.

答案1

得分: 1

使用声明的类型,您可以实现json.Unmarshaler接口来自定义JSON的反序列化过程。

在实现中,您可以通过查看第一个和最后一个字节来判断JSON数据是表示对象还是数组,即查看它们是否为{}[]。根据这个检查,您可以决定如何进一步处理,以下是一个示例:

type Attr struct {
	Type  string
	Value interface{}
}

type AttrList []Attr

func (ls *AttrList) UnmarshalJSON(data []byte) error {
	if len(data) == 0 { // 无需处理
		return nil
	}

	switch last := len(data)-1; {
    // 是否为数组?
	case data[0] == '[' && data[last] == ']':
		return json.Unmarshal(data, (*[]Attr)(ls))

    // 是否为对象?
	case data[0] == '{' && data[last] == '}':
		var obj map[string]interface{}
		if err := json.Unmarshal(data, &obj); err != nil {
			return err
		}
		for key, value := range obj {
			*ls = append(*ls, Attr{Type: key, Value: value})
		}
		return nil
	}

	return errors.New("不支持的AttrList JSON类型")
}

https://go.dev/play/p/X5LV8G87bLJ

英文:

With a declared type you can implement the json.Unmarshaler interface to customize how the JSON will be unmarshaled.

In the implementation you can check whether or not the JSON data represents an Object or an Array by simply looking at the first and last byte to see if its {-and-} or [-and-]. Based on that check you can then decide how to proceed further, here's an example:

type Attr struct {
	Type  string
	Value interface{}
}

type AttrList []Attr

func (ls *AttrList) UnmarshalJSON(data []byte) error {
	if len(data) == 0 { // nothing to do
		return nil
	}

	switch last := len(data)-1; {
    // is array?
	case data[0] == '[' && data[last] == ']':
		return json.Unmarshal(data, (*[]Attr)(ls))

    // is object?
	case data[0] == '{' && data[last] == '}':
		var obj map[string]interface{}
		if err := json.Unmarshal(data, &obj); err != nil {
			return err
		}
		for key, value := range obj {
			*ls = append(*ls, Attr{Type: key, Value: value})
		}
		return nil
	}

	return errors.New("unsupported JSON type for AttrList")
}

https://go.dev/play/p/X5LV8G87bLJ

huangapple
  • 本文由 发表于 2022年4月7日 19:13:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/71781141.html
匿名

发表评论

匿名网友

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

确定