如何根据键前缀解码JSON对象

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

How to decode JSON object based on key prefix

问题

我在想是否可以根据前缀将JSON对象解码为结构体。

例如,我可能有两个如下的JSON对象:

{
    "id teacher": "10"
}

{
    "id student": "20"
}

目前我有两个结构体:

type Teacher struct {
    Id  string  `json:"id teacher"`
}

type Student struct {
    Id  string  `json:"id student"`
}

我想知道是否可以只使用一个结构体,并根据字符串的前缀(例如,使用正则表达式id.*)进行解码,假设只会有一个匹配的字段。

英文:

I'm wondering if it is possible to decode a JSON object into struct based on prefix.

For example, I may have two JSON objects like following:

{
    "id teacher": "10"
}

and

{
    "id student": "20"
}

Currently I have two structs:

type Teacher struct {
    Id  string  `json:"id teacher"`
}

type Student struct {
    Id  string  `json:"id student"`
}

I'm wondering if it is possible to have one struct and decode based on the prefix of the string (for example, by regex id.*) assuming that there will be only one matching field.

答案1

得分: 2

如果我理解你的意图正确的话,你想创建一个名为Person的结构体,并且有一个名为Person.Id的属性,可以由id teacherid student填充。

在原生的encoding/json语法中,你可能期望看到类似下面的代码,但是Go语言不是这样工作的。

type Person struct {
    Id string `json:"id student|id teacher"`
}

一种方法是实现一个自定义的UnmarshalJSON函数,如下所示。这个例子使用了strings.Index,但是使用正则表达式也同样简单。

type Person struct {
	Id   string
	Role string
}

func (p *Person) UnmarshalJSON(data []byte) error {
	var v map[string]interface{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}

	for key, val := range v {
		if strings.Index(key, "id ") == 0 {
			p.Id = val.(string)
			p.Role = key[3:]
		}
	}

	return nil
}

这里有一个完整可运行的例子:

https://play.golang.org/p/1-tzUYcd5rJ

英文:

If I understand what you're trying to do, you want to create a single struct for say Person and have a single property Person.Id which can be populated by either id teacher or id student.

In native encoding/json syntax, you might expect to see something like the following, but Go doesn't work this way.

type Person struct {
    Id string `json:"id student|id teacher"`
}

One approach is to implement a custom UnmarshalJSON function like follows. This example uses strings.Index but it's just as easy to use a regular expression.

type Person struct {
	Id   string
	Role string
}

func (p *Person) UnmarshalJSON(data []byte) error {
	var v map[string]interface{}
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}

	for key, val := range v {
		if strings.Index(key, "id ") == 0 {
			p.Id = val.(string)
			p.Role = key[3:]
		}
	}

	return nil
}

Here's a fully operational example:

https://play.golang.org/p/1-tzUYcd5rJ

huangapple
  • 本文由 发表于 2021年7月19日 06:23:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/68433493.html
匿名

发表评论

匿名网友

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

确定