GOLang:嵌套 XML 到 JSON

GOLang: Nested XML to JSON

你好 Whosebugers!!

我正在尝试弄清楚如何给定 XML 输入,然后使用 Golang 将其转换为 JSON。例如...

<version>0.1</version> <termsofService>http://www.wunderground.com/weather/api/d/terms.html</termsofService> <features> <feature>conditions</feature> </features>

会变成

"version": "0.1", "termsofService": "http://www.wunderground.com/weather/api/d/terms.html", "features": { "feature": "conditions" },

我得到的 versiontermsofservice 是正确的,但我不知道如何 return 嵌套的 features。这是我必须硬编码的东西吗?

代码:

    type reportType struct{
    Version xml.CharData        `xml:"version"`
    TermsOfService xml.CharData `xml:"termsofService"
    `
    Features xml.CharData       `xml:"features>feature"`
    Zip      xml.CharData       `xml:"current_observation>display_location>zip"`
    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    string `json:"features feature" `;
    Zip           string `json:"current_observation > display_location > zip"`;
}
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 := "YouDontNeedToKnow"
    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= string(report.Features)
    output.Zip=string(report.Zip)
    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())
    }


}

输出:

JSON output nicely formatted: { "version": "0.1", "termsofService": "http://www.wunderground.com/weather/api/d/terms.html", "features \u003e feature": "conditions", "current_observation \u003e display_location \u003e zip": "64068" }

感谢您的宝贵时间!

您没有获得所需的输出,因为您的 json 结构定义不正确。你有;

type reportTypeJson struct{
    Version        string  `json:"version"`;
    TermsOfService string `json:"termsofService"`;
    Features    string `json:"features feature" `;
    Zip           string `json:"current_observation > display_location > zip"`;
}

将特征表示为字符串,但它实际上是一个对象,可以是 map[string]string 或者它自己的结构,可以这样定义;

type Features struct {
     Feature string `json:"feature"`
}

鉴于字段名称是复数,我猜想它是一个集合,因此将您的结构更改为

type reportTypeJson struct{
    Version        string  `json:"version"`;
    TermsOfService string `json:"termsofService"`;
    Features    map[string]string `json:"features"`;
    Zip           string `json:"current_observation > display_location > zip"`;
}

可能就是您要找的。当然,这意味着你必须修改一些其他代码,这些代码将 xml 结构的值分配给 json 一个或其他任何东西,但我认为你可以自己解决这个问题:D

编辑:下面的部分是您将 xml 类型转换为 json 类型的地方(即分配 reportTypeJson 的实例并将 reportType 的值分配给它,以便您可以调用json 对其进行编组以产生输出)。假设您正在使用上面 reportTypeJson 的定义,其中 Features 作为 map[string]string,您只需修改设置 output.Features 的那一行。在下面的示例中,我使用 'composite literal' 语法内联执行此操作。这允许您在为集合赋值的同时 instantiate/allocate 集合。

//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{"features":string(report.Features)} // allocate a map, add the 'features' value to it and assign it to output.Features
output.Zip=string(report.Zip)
data,err = json.MarshalIndent(output,"","      ")
doErr(err, "From marshalIndent")
fmt.Printf("JSON output nicely formatted: \n%s\n",data)