英文:
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")
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论