如何将 map[string]interface{} 数据转换为结构体(struct)?

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

how to convert map[string]interface{} data to struct

问题

我不知道如何提问,所以我将用一个例子来提问。

我有一些数据,如下所示:

{
..
	"velocityStatEntries":  {

	"8753": {

		"estimated": {"value": 23.0,"text": "23.0"},

		"completed": {"value": 27.0,"text": "27.0"}
	},

	"8673": {

		"estimated": {"value": 54.5,"text": "54.5"},

		"completed": {"value": 58.5,"text": "58.5"}
	},
	.
	.
	.

	}
..
}

我想声明一个类型,将映射键值作为它的"KEY"或我指定的任何属性。是否可以在不使用映射迭代的情况下实现?

期望的输出:

{...
   "velocityStatEntries": {
   {
	 "key": "8753",
	 "estimated": {"value": 54.5,"text": "54.5"},
	 "completed": {"value": 58.5,"text": "58.5"}
   },
   {
	 "key": "8673",
	 "estimated": {"value": 54.5,"text": "54.5"},
	 "completed": {"value": 58.5,"text": "58.5"}
   },
  }
...
}

这是我所做的:

type VelocityStatEntry struct {
	Key string
	Estimated struct {
		Value float64 `json:"value"`
		Text  string  `json:"text"`
	} `json:"estimated"`
	Completed struct {
		Value float64 `json:"value"`
		Text  string  `json:"text"`
	} `json:"completed"`
}

type RapidChartResponse struct {
	...
	VelocityStatEntries map[string]VelocityStatEntry `json:"velocityStatEntries"`
	..
}

但它不起作用。我想将字符串映射键值作为KEY属性。

英文:

I do not know how to ask, so i will ask with an example.

I have some data like that

{
..
	"velocityStatEntries":  {

	"8753":  {

		"estimated":  {"value":  23.0,"text":  "23.0"},

		"completed":  {"value":  27.0,"text":  "27.0"}
	},

	"8673":  {

		"estimated":  {"value":  54.5,"text":  "54.5"},

		"completed":  {"value":  58.5,"text":  "58.5"}
	},
	.
	.
	.

	}
..
}

I want to declare a type that takes map key to its "KEY" or any property that is given by me.
Is it possible without using map iteration?

Expected output:

{...
   "velocityStatEntries": {
   {
	 "key": "8753",
	 "estimated":  {"value":  54.5,"text":  "54.5"},
	 "completed":  {"value":  58.5,"text":  "58.5"}
   },
   {
	 "key": "8673",
	 "estimated":  {"value":  54.5,"text":  "54.5"},
	 "completed":  {"value":  58.5,"text":  "58.5"}
   },
  }
...
}

This is what i have done

type VelocityStatEntry struct {
	Key string
	Estimated struct {
		Value float64 `json:"value"`
		Text  string  `json:"text"`
	} `json:"estimated"`
	Completed struct {
		Value float64 `json:"value"`
		Text  string  `json:"text"`
	} `json:"completed"`
}

type RapidChartResponse struct {
	...
	VelocityStatEntries map[string]VelocityStatEntry `json:"velocityStatEntries"`
	..
}

But it is not working. I want to take that string map key to KEY property.

答案1

得分: 3

如果数据源是JSON格式的,那么你应该跳过map[string]interface{},而是使用你所需的自定义解组器(custom unmarshaler)来实现你想要的功能。可以考虑使用map[string]json.RawMessage。但是,如果可能的话,尽量避免使用map[string]interface{}转换为结构体,因为这样做会很麻烦。

例如:

type VelocityStatEntryList []*VelocityStatEntry

func (ls *VelocityStatEntryList) UnmarshalJSON(data []byte) error {
	var m map[string]json.RawMessage
	if err := json.Unmarshal(data, &m); err != nil {
		return err
	}
	for k, v := range m {
		e := &VelocityStatEntry{Key: k}
		if err := json.Unmarshal([]byte(v), e); err != nil {
			return err
		}
		*ls = append(*ls, e)
	}
	return nil
}

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

英文:

If the data originates from JSON then you should skip the map[string]interface{} and instead use a custom unmarshaler implemented by your desired struct that does what you want. Perhaps by utilizing a map[string]json.RawMessage. But map[string]interface{} to struct conversion is a pain, avoid it if possible.

For example:

type VelocityStatEntryList []*VelocityStatEntry

func (ls *VelocityStatEntryList) UnmarshalJSON(data []byte) error {
	var m map[string]json.RawMessage
	if err := json.Unmarshal(data, &m); err != nil {
		return err
	}
	for k, v := range m {
		e := &VelocityStatEntry{Key: k}
		if err := json.Unmarshal([]byte(v), e); err != nil {
			return err
		}
		*ls = append(*ls, e)
	}
	return nil
}

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

huangapple
  • 本文由 发表于 2022年1月7日 21:29:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/70621975.html
匿名

发表评论

匿名网友

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

确定