在Golang中,是否可以为JSON同时使用动态键和静态键的结构?

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

Is it possible to have a structure for dynamic keys along with static keys for json in Golang

问题

抱歉,我只能为您提供翻译服务,无法解答关于Golang的问题。以下是您要翻译的内容:

对于这个基础问题我表示抱歉。我对Golang还不熟悉,我有以下要解析的json数据:

{
   "config1":{
      "Parameters":{
         "Pm1":"value",
         "Pm2":"value",
         "Pm3":"value"
      },
      "dynamic_key1":{
         "Parameters":{
            "a":"value",
            "b":"value",
            "c":"value",
            "d":"value"
         },
         "Epoch":"value"
      },
      "Epoch":"value"
   }
}

我尝试编写一个结构体来解析这个json数据,并按照以下方式编写了结构体:

type Parameters struct {
    Pm1 string `json:"Pm1"`
    Pm2 string `json:"Pm2"`
    Pm3 string `json:"Pm3"`
}

type dynamicParametes struct {
    a string `json:"a"`
    b string `json:"b"`
    c string `json:"c"`
    d string `json:"d"`
}

type dynamic struct {
    Parameters dynamicParametes `json:"Parameters"`
    Epoch      string           `json:"Epoch"`
}

type config1 struct {
    Parameters   Parameters         `json:"Parameters"`
    Dynamic_keys map[string]dynamic `json:"-"`
    Epoch        string             `json:"Epoch"`
}

type config struct {
    config1 config1 `json:"config1"`
}

我希望map能够将所有匹配的键与dynamic结构体匹配,并在map中显示它们。但是,我发现它创建了一个空的map作为响应。

英文:

My apologies for the basic question. I am new to Golang and I have the json to parse as below

{
   "config1":{
      "Parameters":{
         "Pm1":"value",
         "Pm2":"value",
         "Pm3":"value"
      },
      "dynamic_key1":{
         "Parameters":{
            "a":"value",
            "b":"value",
            "c":"value",
            "d":"value"
         },
         "Epoch":"value"
      },
      "Epoch":"value"
   }
}

I am trying to write a struct to parse this json and wrote the struct in the following way.

type Parameters struct {
	Pm1 string `json:"Pm1"`
	Pm2 string `json:"Pm2"`
	Pm3 string `json:"Pm3"`
}

type dynamicParametes struct {
	a string `json:"a"`
	b string `json:"b"`
	c string `json:"c"`
	d string `json:"d"`
}

type dynamic struct {
	Parameters dynamicParametes `json:"Parameters"`
	Epoch      string           `json:"Epoch"`
}

type config1 struct {
	Parameters   Parameters         `json:"Parameters"`
	Dynamic_keys map[string]dynamic `json:"-"`
	Epoch        string             `json:"Epoch"`
}

type config struct {
	config1 config1 `json:"config1"`
}

I was hoping that the map will match all the matching keys with dynamic structs and show them in the map. But, I see it created an empty map in the response.

答案1

得分: 2

实现了自定义的配置类型的反序列化器。

注意:

  • 如果你不需要将ParametersdynamicParametes作为结构类型,你可以简单地将它们反序列化为map[string]string类型。
  • 你必须将你的结构体中的所有字段都公开以进行JSON反序列化。
  • 验证你的JSON字符串。
type config struct {
	Config1 config1 `json:"config1"`
}

type _config config

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

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

	c := _config{}
	err := json.Unmarshal(data, &c)
	if err != nil {
		return err
	}
	
	b.Config1.Parameters = c.Config1.Parameters
	b.Config1.Epoch = c.Config1.Epoch

	if b.Config1.Dynamic_keys == nil {
		b.Config1.Dynamic_keys = map[string]dynamic{}
	}

	for key, config := range v.Config1 {
		if key == "Parameters" || key == "Epoch" {
			continue
		}
		data, err := json.Marshal(config)
		if err != nil {
			return err
		}

		d := dynamic{}
		err = json.Unmarshal(data, &d)
		if err != nil {
			return err
		}
		b.Config1.Dynamic_keys[key] = d
	}

	return nil
}

你可以在这里查看完整的代码。

英文:

Implemented custom unmarshler for config type.

Note

  • If you don't need Parameters and dynamicParametes as struct types, you can simply unmarshal them into map[string]string

  • you have to expose all fields in your structs to do json unmarshaling

  • validate your json string

type config struct {
	Config1 config1 `json:"config1"`
}

type _config config

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

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

	c := _config{}
	err := json.Unmarshal(data, &c)
	if err != nil {
		return err
	}
	
	b.Config1.Parameters = c.Config1.Parameters
	b.Config1.Epoch = c.Config1.Epoch

	if b.Config1.Dynamic_keys == nil {
		b.Config1.Dynamic_keys = map[string]dynamic{}
	}

	for key, config := range v.Config1 {
		if key == `Parameters` || key == `Epoch` {
			continue
		}
		data, err := json.Marshal(config)
		if err != nil {
			return err
		}

		d := dynamic{}
		err = json.Unmarshal(data, &d)
		if err != nil {
			return err
		}
		b.Config1.Dynamic_keys[key] = d
	}

	return nil
}

you can see full code here

答案2

得分: -1

你所需要做的就是理解 JSON 中的基本数据类型的表示方式。

在你的 JSON 中,字段 Parameters 是一个简单的 map[string]string,你可以使用标准的 json.Unmarshal 进行解组,无需实现额外的 json.Unmarshaler 接口。

以下是带有代码的 Go Playground 链接:

Go Playground 链接

package main

import (
	"encoding/json"
	"fmt"
)

const jsonStr = `{
   "config1":{
      "Parameters":{
         "Pm1":"value_1",
         "Pm2":"value_2",
         "Pm3":"value_3"
      },
      "dynamic_key1":{
         "Parameters":{
            "a":"value_1",
            "b":"value_2",
            "c":"value_3",
            "d":"value_4"
         },
         "Epoch":"value"
      },
      "Epoch":"value"
   }
}`

type Data struct {
	Config1 struct {
		Parameters map[string]string `json:"Parameters"`
		Dynamic    struct {
			Parameters map[string]string `json:"Parameters"`
			Epoch      string            `json:"Epoch"`
		} `json:"dynamic_key1"`
		Epoch string `json:"Epoch"`
	} `json:"config1"`
}

func main() {
	var data Data

	_ = json.Unmarshal([]byte(jsonStr), &data)

	fmt.Printf("%+v\n", data)
}

输出结果:

{Config1:{Parameters:map[Pm1:value_1 Pm2:value_2 Pm3:value_3] Dynamic:{Parameters:map[a:value_1 b:value_2 c:value_3 d:value_4] Epoch:value} Epoch:value}}

希望对你有所帮助!

英文:

All you need is understand how base data types looks in json.

Field Parameters in your json is simple map[string]string and you can unmarshall it with standart json.Unmasrhall without any aditional implementation of interface json.Unmarshaler.

Link for Go Playground with code below

package main

import (
	"encoding/json"
	"fmt"
)

const jsonStr = `{
   "config1":{
      "Parameters":{
         "Pm1":"value_1",
         "Pm2":"value_2",
         "Pm3":"value_3"
      },
      "dynamic_key1":{
         "Parameters":{
            "a":"value_1",
            "b":"value_2",
            "c":"value_3",
            "d":"value_4"
         },
         "Epoch":"value"
      },
      "Epoch":"value"
   }
}`

type Data struct {
	Config1 struct {
		Parameters map[string]string `json:"Parameters"`
		Dynamic    struct {
			Parameters map[string]string `json:"Parameters"`
			Epoch      string            `json:"Epoch"`
		} `json:"dynamic_key1"`
		Epoch string `json:"Epoch"`
	} `json:"config1"`
}

func main() {
	var data Data

	_ = json.Unmarshal([]byte(jsonStr), &data)

	fmt.Printf("%+v\n", data)
}

Output:

{Config1:{Parameters:map[Pm1:value_1 Pm2:value_2 Pm3:value_3] Dynamic:{Parameters:map[a:value_1 b:value_2 c:value_3 d:value_4] Epoch:value} Epoch:value}}

huangapple
  • 本文由 发表于 2021年6月13日 03:17:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/67952261.html
匿名

发表评论

匿名网友

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

确定