XML 到 JSON 多重嵌套
XML into JSON Multiple Nesting
我正在尝试编写代码将 XML 转换为 JSON。我要翻译的 XML 如下...
(只是一个片段)
`<version>0.1</version>
<termsofService>http://www.wunderground.com/weather/api/d/terms.html</termsofService>
<features>
<feature>conditions</feature>
</features>
<current_observation>
<image>
<url>http://icons.wxug.com/graphics/wu2/logo_130x80.png</url>
<title>Weather Underground</title>
<link>http://www.wunderground.com</link>
</image>
<display_location>
<full>Kearney, MO</full>
<city>Kearney</city>
<state>MO</state>
<state_name>Missouri</state_name>`
当前代码:
`package main
import (
"fmt"
"net/url"
"encoding/xml"
"net/http"
"log"
"io/ioutil"
"encoding/json"
)
type reportType struct{
Version xml.CharData `xml:"version"`
TermsOfService xml.CharData `xml:"termsofService"
`
Features xml.CharData `xml:"features>feature"`
Full xml.CharData `xml:"current_observation>display_location>full"`
StateName xml.CharData `xml:"current_observation>display_location>state_name"`
WindGust xml.CharData `xml:"current_observation>observation_location>full"`
Problem myErrorType `xml:"error"`
}
type myErrorType struct{
TypeOfError xml.CharData `xml:"type"`
Desciption xml.CharData `xml:"description"`
}
type reportTypeJson struct{
Version string `json:"version"`;
TermsOfService string `json:"termsofService"`;
Features map[string]string `json:"features"`;
Full map[string]string `json:"display_location"`;
WindGust map[string]string `json:"observation_location"`
}
func main() {
fmt.Println("data is from WeatherUnderground.")
fmt.Println("https://www.wunderground.com/")
var state, city string
str1 := "What is your state?"
str2 := "What is your city?"
fmt.Println(str1)
fmt.Scanf("%s", &state)
fmt.Println(str2)
fmt.Scanf("%s", &city)
baseURL := "http://api.wunderground.com/api/";
apiKey := "3hunna"
var query string
//set up the query
query = baseURL+apiKey +
"/conditions/q/"+
url.QueryEscape(state)+ "/"+
url.QueryEscape(city)+ ".xml"
fmt.Println("The escaped query: "+query)
response, err := http.Get(query)
doErr(err, "After the GET")
var body []byte
body, err = ioutil.ReadAll(response.Body)
doErr(err, "After Readall")
fmt.Println(body);
fmt.Printf("The body: %s\n",body)
//Unmarshalling
var report reportType
xml.Unmarshal(body, &report)
fmt.Printf("The Report: %s\n", report)
fmt.Printf("The description is [%s]\n",report.Problem.Desciption)
//Now marshal the data out in JSON
var data []byte
var output reportTypeJson
output.Version = string(report.Version);
output.TermsOfService = string(report.TermsOfService)
output.Features= map[string]string{"feature":string(report.Features)} // allocate a map, add the 'features' value to it and assign it to output.Features
output.Full=map[string]string{"full":string(report.Full),"state_name":string(report.StateName)}
output.WindGust=map[string]string{"full":string(report.WindGust)}
data,err = json.MarshalIndent(output,""," ")
doErr(err, "From marshalIndent")
fmt.Printf("JSON output nicely formatted: \n%s\n",data)
}
func doErr( err error, message string){
if err != nil{
log.Panicf("ERROR: %s %s \n", message, err.Error())
}
}
如您所见,我正在使用地图来映射一级嵌套,例如 features
的情况。但是对于像 xml:"current_observation>display_location>state_name"
这样的两层嵌套情况,我不知道如何创建第一层,在这种情况下 current_observations
。有没有办法以某种方式创建各种地图的地图?非常感谢任何和所有的想法,因为我现在很困惑,谢谢你的时间!
输出:
JSON output nicely formatted:
{
"version": "0.1",
"termsofService": "http://www.wunderground.com/weather/api/d/terms.html",
"features": {
"feature": "conditions"
},
"display_location": {
"full": "Kearney, MO",
"state_name": "Missouri"
},
"observation_location": {
"full": "Stonecrest, Kearney, Missouri"
}
}
您可以使用结构或地图的地图。我将给出两者的一些例子,从地图的地图开始。该类型将声明为;
CurrentObservation map[string]map[string]string `json:"current_observation"`
在这种情况下,您有一个以字符串作为键的映射,而值是另一个以字符串作为键和值的映射。结果,当您编组 json 时,您最终会得到类似的东西;
"current_observation" {
"image": { // first level where the value is a map[string]string
"title":"Weather Underground" // inner map, string to string
}
}
如果说您只想打印标题,您会这样做;
fmt.Println(reportJson.CurrentObservation["image"]["title"])
由于那里的数据看起来相当静态,您也可以改用结构。在这种情况下,你会使用这样的东西;
CurrentObservation CurrentObservation `json:"current_observation"`
type CurrentObservation struct {
Image Image `json:"image"`
}
type Image struct {
Url string `json:"url"`
Title string `json:"title"`
Link string `json:"link"`
}
这两个选项产生相同的输出,尽管它们对于不同的输入可能表现不同。例如,如果收到另一个版本的 current_observation
作为输入,例如其中有另一个嵌套项调用它... previous_observation
那么 map 选项将自动解组此数据以及结构选项将排除它,因为在 Go 中没有映射到任何 object/type。
个人而言,我更喜欢结构路由,但它因情况而异。对于您的应用程序,地图可能更好,因为您没有使用输入(它以 xml 形式出现)并且您只想打印它,您实际上不必处理 current_observation
,如果里面有3个objects,它们都会按预期输出,如果是5就一样了。使用这些结构,您必须显式定义每个字段,如果您只是转换输入,这并不是真正必要的。该结构的优势更多地用于稍后在您具有类型安全性的地方,尽管在这种情况下,我会说它们仍然相当等效,因为例如任何时候您想要访问图像中的某些内容,例如 CurrentObservation.Image.Title
你'我必须执行检查以确保图像不为零,例如;
if CurrentObservation.Image != nil {
fmt.Println(CurrentObservation.Image.Title)
}
使用 map 你基本上有相同的开销,只是你在检查一个键的存在而不是检查一个内部结构是否为 nil。
编辑:使用复合文字语法初始化地图地图的示例;
reportJson.CurrentObservation := map[string]map[string]string {
"display_location": map[string]string {
"full": report.Full,
"state_name": report.StateName,
},
}
我正在尝试编写代码将 XML 转换为 JSON。我要翻译的 XML 如下...
(只是一个片段)
`<version>0.1</version>
<termsofService>http://www.wunderground.com/weather/api/d/terms.html</termsofService>
<features>
<feature>conditions</feature>
</features>
<current_observation>
<image>
<url>http://icons.wxug.com/graphics/wu2/logo_130x80.png</url>
<title>Weather Underground</title>
<link>http://www.wunderground.com</link>
</image>
<display_location>
<full>Kearney, MO</full>
<city>Kearney</city>
<state>MO</state>
<state_name>Missouri</state_name>`
当前代码:
`package main
import (
"fmt"
"net/url"
"encoding/xml"
"net/http"
"log"
"io/ioutil"
"encoding/json"
)
type reportType struct{
Version xml.CharData `xml:"version"`
TermsOfService xml.CharData `xml:"termsofService"
`
Features xml.CharData `xml:"features>feature"`
Full xml.CharData `xml:"current_observation>display_location>full"`
StateName xml.CharData `xml:"current_observation>display_location>state_name"`
WindGust xml.CharData `xml:"current_observation>observation_location>full"`
Problem myErrorType `xml:"error"`
}
type myErrorType struct{
TypeOfError xml.CharData `xml:"type"`
Desciption xml.CharData `xml:"description"`
}
type reportTypeJson struct{
Version string `json:"version"`;
TermsOfService string `json:"termsofService"`;
Features map[string]string `json:"features"`;
Full map[string]string `json:"display_location"`;
WindGust map[string]string `json:"observation_location"`
}
func main() {
fmt.Println("data is from WeatherUnderground.")
fmt.Println("https://www.wunderground.com/")
var state, city string
str1 := "What is your state?"
str2 := "What is your city?"
fmt.Println(str1)
fmt.Scanf("%s", &state)
fmt.Println(str2)
fmt.Scanf("%s", &city)
baseURL := "http://api.wunderground.com/api/";
apiKey := "3hunna"
var query string
//set up the query
query = baseURL+apiKey +
"/conditions/q/"+
url.QueryEscape(state)+ "/"+
url.QueryEscape(city)+ ".xml"
fmt.Println("The escaped query: "+query)
response, err := http.Get(query)
doErr(err, "After the GET")
var body []byte
body, err = ioutil.ReadAll(response.Body)
doErr(err, "After Readall")
fmt.Println(body);
fmt.Printf("The body: %s\n",body)
//Unmarshalling
var report reportType
xml.Unmarshal(body, &report)
fmt.Printf("The Report: %s\n", report)
fmt.Printf("The description is [%s]\n",report.Problem.Desciption)
//Now marshal the data out in JSON
var data []byte
var output reportTypeJson
output.Version = string(report.Version);
output.TermsOfService = string(report.TermsOfService)
output.Features= map[string]string{"feature":string(report.Features)} // allocate a map, add the 'features' value to it and assign it to output.Features
output.Full=map[string]string{"full":string(report.Full),"state_name":string(report.StateName)}
output.WindGust=map[string]string{"full":string(report.WindGust)}
data,err = json.MarshalIndent(output,""," ")
doErr(err, "From marshalIndent")
fmt.Printf("JSON output nicely formatted: \n%s\n",data)
}
func doErr( err error, message string){
if err != nil{
log.Panicf("ERROR: %s %s \n", message, err.Error())
}
}
如您所见,我正在使用地图来映射一级嵌套,例如 features
的情况。但是对于像 xml:"current_observation>display_location>state_name"
这样的两层嵌套情况,我不知道如何创建第一层,在这种情况下 current_observations
。有没有办法以某种方式创建各种地图的地图?非常感谢任何和所有的想法,因为我现在很困惑,谢谢你的时间!
输出:
JSON output nicely formatted:
{
"version": "0.1",
"termsofService": "http://www.wunderground.com/weather/api/d/terms.html",
"features": {
"feature": "conditions"
},
"display_location": {
"full": "Kearney, MO",
"state_name": "Missouri"
},
"observation_location": {
"full": "Stonecrest, Kearney, Missouri"
}
}
您可以使用结构或地图的地图。我将给出两者的一些例子,从地图的地图开始。该类型将声明为;
CurrentObservation map[string]map[string]string `json:"current_observation"`
在这种情况下,您有一个以字符串作为键的映射,而值是另一个以字符串作为键和值的映射。结果,当您编组 json 时,您最终会得到类似的东西;
"current_observation" {
"image": { // first level where the value is a map[string]string
"title":"Weather Underground" // inner map, string to string
}
}
如果说您只想打印标题,您会这样做;
fmt.Println(reportJson.CurrentObservation["image"]["title"])
由于那里的数据看起来相当静态,您也可以改用结构。在这种情况下,你会使用这样的东西;
CurrentObservation CurrentObservation `json:"current_observation"`
type CurrentObservation struct {
Image Image `json:"image"`
}
type Image struct {
Url string `json:"url"`
Title string `json:"title"`
Link string `json:"link"`
}
这两个选项产生相同的输出,尽管它们对于不同的输入可能表现不同。例如,如果收到另一个版本的 current_observation
作为输入,例如其中有另一个嵌套项调用它... previous_observation
那么 map 选项将自动解组此数据以及结构选项将排除它,因为在 Go 中没有映射到任何 object/type。
个人而言,我更喜欢结构路由,但它因情况而异。对于您的应用程序,地图可能更好,因为您没有使用输入(它以 xml 形式出现)并且您只想打印它,您实际上不必处理 current_observation
,如果里面有3个objects,它们都会按预期输出,如果是5就一样了。使用这些结构,您必须显式定义每个字段,如果您只是转换输入,这并不是真正必要的。该结构的优势更多地用于稍后在您具有类型安全性的地方,尽管在这种情况下,我会说它们仍然相当等效,因为例如任何时候您想要访问图像中的某些内容,例如 CurrentObservation.Image.Title
你'我必须执行检查以确保图像不为零,例如;
if CurrentObservation.Image != nil {
fmt.Println(CurrentObservation.Image.Title)
}
使用 map 你基本上有相同的开销,只是你在检查一个键的存在而不是检查一个内部结构是否为 nil。
编辑:使用复合文字语法初始化地图地图的示例;
reportJson.CurrentObservation := map[string]map[string]string {
"display_location": map[string]string {
"full": report.Full,
"state_name": report.StateName,
},
}