Golang:用于生成/解析XML和JSON的结构体

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

Golang: structure to generate/parse both XML and JSON

问题

使用相同的结构来生成XML和JSON,而不是为每个格式创建单独的结构。目前的解决方案产生了不符合要求的JSON结果。是否有其他方法可以解决这个问题,而不是使用单独的结构来处理XML和JSON?

英文:

The use case is to generate (and parse) the following XML and JSON not creating separate structures for every of them.

XML

<xxx xmlns="http://example.org/ns">
    <data type="plaintext">Hello</data>

    <field1>Something1</field1>
    <field2>Something2</field2>
    ...
</xxx>

JSON

{
    "data": "Hello",
    "data_type": "plaintext",

    "field1": "Something1",
    "field2": "Something2"
    ...
}

Possible solution would be:

type Xxx struct {
    XMLName xml.Name `xml:"http://example.org/ns xxx" json:"-"`

    // **If only "inline" attribute had existed**
    Data    Data     `xml:"data" json:",inline"`

    // There are a lot of other fields here
    Field1  string   `xml:"field1" json:"field1"`
    Field2  string   `xml:"field2" json:"field2"`
    ...
}

type Data struct {
    Value string `xml:",chardata" json:"data"`
    Type  string `xml:"type,attr" data_type:"data"`
}

However, right now it produces the following JSON:

{"Data": {"data": "Hello", "type": "plaintext"}, "field1": "Something1", "field2": "Something2"}

which is not what I need. So, is there any other way to solve the problem not using separate structures for xml and json?

答案1

得分: 2

解决方案是编写自定义的MarshalJSON(或MarshalXML)和UnmarshalJSON(或UnmarshalXML)来处理文本表示中的差异。示例代码如下:

func (x *Xxx) MarshalJSON() ([]byte, error) {
    return []byte(`{"data": "` + x.Data.Value + `","type":"` + x.Data.Type + `","field1":"` + x.Field1 + `","field2":"` + x.Field2 + `"}`), nil
}

这个示例只是为了演示原理而粗略编写的。为了更高效,你应该使用另一个结构来处理这个过程。这个结构不需要被导出(实际上你不希望导出它),只需要存在并被你的函数使用。示例代码如下:

type xxxJSON struct {
    Data   string
    Type   string
    Field1 string
    Field2 string
}

func (x *Xxx) MarshalJSON() ([]byte, error) {
    out := xxxJSON{}
    out.Data = x.Data.Value
    out.Type = x.Data.Type
    out.Field1 = x.Field1
    out.Field2 = x.Field2
    return json.Marshal(out)
}

以上是翻译好的内容,请确认是否满意。

英文:

The solution is to write a custom MarshalJSON (or MarshalXML) and UnmarshalJSON (or UnmarshalXML) to handle the differences in your text-representations. Example:

func (x *Xxx) MarshalJSON() ([]byte, error) {
    return []byte(`{"data": "` + x.Data.Value + `","type":"` + x.Data.Type + `","field1":"` + x.Field1 + `","field2":"` + x.Field2 + `"}`), nil
}

This example is a rough one to demonstrate the principle. For something more efficient, you should use another structure to handle the process. This structure doesn't need to be exported (in fact you don't want to export it), just to be there and used by your function. Example:

type xxxJSON struct {
    Data string
    Type string
    Field1 string
    Field2 string
}

func (x *Xxx) MarshalJSON() ([]byte, error) {
    out := xxxJSON{}
    out.Data = x.Data.Value
    out.Type = x.Data.Type
    out.Field1 = x.Field1
    out.Field2 = x.Field2
    return json.Marshal(out)
}

huangapple
  • 本文由 发表于 2014年6月14日 19:41:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/24219545.html
匿名

发表评论

匿名网友

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

确定