英文:
Unmarshaling nested xml golang
问题
我想将一个嵌套的 XML 转换为 Golang 结构体。我想要转换的 XML 如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<status>
<authorized>true</authorized>
<plan>Basic</plan>
<usage_reports>
<usage_report metric="hits" period="day">
<period_start>2021-07-20 00:00:00 +0000</period_start>
<period_end>2021-07-21 00:00:00 +0000</period_end>
<max_value>1000000</max_value>
<current_value>0</current_value>
</usage_report>
<usage_report metric="hits.82343" period="day">
<period_start>2021-07-20 00:00:00 +0000</period_start>
<period_end>2021-07-21 00:00:00 +0000</period_end>
<max_value>1000000</max_value>
<current_value>0</current_value>
</usage_report>
</usage_reports>
</status>
为了进行转换,我定义了两个 Golang 结构体,如下所示:
// UsageReport 表示特定指标的使用报告。
type UsageReport struct {
Usage string `xml:"usage_report,chardata"`
Metric string `xml:"metric,attr"`
Period string `xml:"period,attr"`
Start string `xml:"period_start"`
End string `xml:"period_end"`
Max int64 `xml:"max_value"`
Current int64 `xml:"current_value"`
}
// AuthResponse 表示授权调用的响应结构。
type AuthResponse struct {
Status xml.Name `xml:"status"`
Authorized bool `xml:"authorized"`
Plan string `xml:"plan"`
Usages []UsageReport `xml:"usage_reports>usage_report"`
}
但是当我尝试使用 xml.Unmarshal
进行转换时,只有 Plan
和 Authorized
的值被转换。转换的结果如下所示:
XML: {{ } true Basic []}
英文:
I want to unmarshall a nested xml to a golang struct. The xml that I want to unmarshall is shown below.
<?xml version="1.0" encoding="UTF-8"?>
<status>
<authorized>true</authorized>
<plan>Basic</plan>
<usage_reports>
<usage_report metric="hits" period="day">
<period_start>2021-07-20 00:00:00 +0000</period_start>
<period_end>2021-07-21 00:00:00 +0000</period_end>
<max_value>1000000</max_value>
<current_value>0</current_value>
</usage_report>
<usage_report metric="hits.82343" period="day">
<period_start>2021-07-20 00:00:00 +0000</period_start>
<period_end>2021-07-21 00:00:00 +0000</period_end>
<max_value>1000000</max_value>
<current_value>0</current_value>
</usage_report>
</usage_reports>
</status>
To unmarshall I have defined two go structs as follows.
// UsageReport represents the usage report of a particular metric.
type UsageReport struct {
Usage string `xml:"usage_report,chardata"`
Metric string `xml:"metric,attr"`
Period string `xml:"period,attr"`
Start string `xml:"period_start"`
End string `xml:"period_end"`
Max int64 `xml:"max_value"`
Current int64 `xml:"current_value"`
}
// AuthResponse represents the structure of the response from authorize calls.
type AuthResponse struct {
Status xml.Name `xml:"status"`
Authorized bool `xml:"authorized"`
Plan string `xml:"plan"`
Usages []UsageReport `xml:"usage_reports"`
}
But when I try to unmarshall using xml.Unmarshal
, only Plan
and Authorized
values gets unmarshalled. The result of unmarshalling is shown below.
XML: {{ } true Basic []}
答案1
得分: 2
请尝试使用这个Go Playground。我使用这个工具来帮助我从XML数据生成Go类型。
package main
import (
"encoding/xml"
"fmt"
)
type Status struct {
XMLName xml.Name `xml:"status"`
Text string `xml:",chardata"`
Authorized string `xml:"authorized"`
Plan string `xml:"plan"`
UsageReports struct {
Text string `xml:",chardata"`
UsageReport []struct {
Text string `xml:",chardata"`
Metric string `xml:"metric,attr"`
Period string `xml:"period,attr"`
PeriodStart string `xml:"period_start"`
PeriodEnd string `xml:"period_end"`
MaxValue string `xml:"max_value"`
CurrentValue string `xml:"current_value"`
} `xml:"usage_report"`
} `xml:"usage_reports"`
}
func main() {
status := Status{}
err := xml.Unmarshal([]byte(xmlStr), &status)
if err != nil {
panic(err)
}
fmt.Println(status.UsageReports.UsageReport[0].MaxValue)
}
const xmlStr = `<?xml version="1.0" encoding="UTF-8"?><status><authorized>true</authorized><plan>Basic</plan><usage_reports><usage_report metric="hits" period="day"><period_start>2021-07-20 00:00:00 +0000</period_start><period_end>2021-07-21 00:00:00 +0000</period_end><max_value>1000000</max_value><current_value>0</current_value></usage_report><usage_report metric="hits.82343" period="day"><period_start>2021-07-20 00:00:00 +0000</period_start><period_end>2021-07-21 00:00:00 +0000</period_end><max_value>1000000</max_value><current_value>0</current_value></usage_report></usage_reports></status>`
英文:
Try this go playground. I use this tool to cheat and help me generate Go types from XML data.
package main
import (
"encoding/xml"
"fmt"
)
type Status struct {
XMLName xml.Name `xml:"status"`
Text string `xml:",chardata"`
Authorized string `xml:"authorized"`
Plan string `xml:"plan"`
UsageReports struct {
Text string `xml:",chardata"`
UsageReport []struct {
Text string `xml:",chardata"`
Metric string `xml:"metric,attr"`
Period string `xml:"period,attr"`
PeriodStart string `xml:"period_start"`
PeriodEnd string `xml:"period_end"`
MaxValue string `xml:"max_value"`
CurrentValue string `xml:"current_value"`
} `xml:"usage_report"`
} `xml:"usage_reports"`
}
func main() {
status := Status{}
err := xml.Unmarshal([]byte(xmlStr), &status)
if err != nil {
panic(err)
}
fmt.Println(status.UsageReports.UsageReport[0].MaxValue)
}
const xmlStr = `<?xml version="1.0" encoding="UTF-8"?><status><authorized>true</authorized><plan>Basic</plan><usage_reports><usage_report metric="hits" period="day"><period_start>2021-07-20 00:00:00 +0000</period_start><period_end>2021-07-21 00:00:00 +0000</period_end><max_value>1000000</max_value><current_value>0</current_value></usage_report><usage_report metric="hits.82343" period="day"><period_start>2021-07-20 00:00:00 +0000</period_start><period_end>2021-07-21 00:00:00 +0000</period_end><max_value>1000000</max_value><current_value>0</current_value></usage_report></usage_reports></status>`
答案2
得分: 1
为了获取Usages
字段的值,请根据mkopriva的建议将xml:"usage_reports"
修改为xml:"usage_reports>usage_report"
。
package main
import (
"encoding/xml"
"fmt"
)
type UsageReport struct {
Metric string `xml:"metric,attr"`
Period string `xml:"period,attr"`
Start string `xml:"period_start"`
End string `xml:"period_end"`
Max int64 `xml:"max_value"`
Current int64 `xml:"current_value"`
}
type AuthResponse struct {
Status xml.Name `xml:"status"`
Authorized bool `xml:"authorized"`
Plan string `xml:"plan"`
Usages []UsageReport `xml:"usage_reports>usage_report"`
}
var data = []byte(`<?xml version="1.0" encoding="UTF-8"?>
<status>
<authorized>true</authorized>
<plan>Basic</plan>
<usage_reports>
<usage_report metric="hits" period="day">
<period_start>2021-07-20 00:00:00 +0000</period_start>
<period_end>2021-07-21 00:00:00 +0000</period_end>
<max_value>1000000</max_value>
<current_value>0</current_value>
</usage_report>
<usage_report metric="hits.82343" period="day">
<period_start>2021-07-20 00:00:00 +0000</period_start>
<period_end>2021-07-21 00:00:00 +0000</period_end>
<max_value>1000000</max_value>
<current_value>0</current_value>
</usage_report>
</usage_reports>
</status>
`)
func main() {
r := AuthResponse{}
if err := xml.Unmarshal(data, &r); err != nil {
panic(err)
}
fmt.Println(r)
}
输出结果:
{{ } true Basic [{hits day 2021-07-20 00:00:00 +0000 2021-07-21 00:00:00 +0000 1000000 0} {hits.82343 day 2021-07-20 00:00:00 +0000 2021-07-21 00:00:00 +0000 1000000 0}]}
英文:
In order to get the value of Usages
field modify xml:"usage_reports"
to xml:"usage_reports>usage_report"
as per the suggestions of mkopriva.
package main
import (
"encoding/xml"
"fmt"
)
type UsageReport struct {
Metric string `xml:"metric,attr"`
Period string `xml:"period,attr"`
Start string `xml:"period_start"`
End string `xml:"period_end"`
Max int64 `xml:"max_value"`
Current int64 `xml:"current_value"`
}
type AuthResponse struct {
Status xml.Name `xml:"status"`
Authorized bool `xml:"authorized"`
Plan string `xml:"plan"`
Usages []UsageReport `xml:"usage_reports>usage_report"`
}
var data = []byte(`<?xml version="1.0" encoding="UTF-8"?>
<status>
<authorized>true</authorized>
<plan>Basic</plan>
<usage_reports>
<usage_report metric="hits" period="day">
<period_start>2021-07-20 00:00:00 +0000</period_start>
<period_end>2021-07-21 00:00:00 +0000</period_end>
<max_value>1000000</max_value>
<current_value>0</current_value>
</usage_report>
<usage_report metric="hits.82343" period="day">
<period_start>2021-07-20 00:00:00 +0000</period_start>
<period_end>2021-07-21 00:00:00 +0000</period_end>
<max_value>1000000</max_value>
<current_value>0</current_value>
</usage_report>
</usage_reports>
</status>
`)
func main() {
r := AuthResponse{}
if err := xml.Unmarshal(data, &r); err != nil {
panic(err)
}
fmt.Println(r)
}
Output:
{{ } true Basic [{hits day 2021-07-20 00:00:00 +0000 2021-07-21 00:00:00 +0000 1000000 0} {hits.82343 day 2021-07-20 00:00:00 +0000 2021-07-21 00:00:00 +0000 1000000 0}]}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论