Reputation: 43
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?
Upvotes: 3
Views: 1888
Reputation: 9509
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)
}
Upvotes: 2