从JSON转换为XML

时间:2016-05-04 21:54:52

标签: json xml go struct output

我在这里看到很多关于从XML转换为JSON的帖子,我最近写了一个这样做的程序,但我也很好奇你将如何从JSON转换为XML?

示例JSON:

"version":"0.1",
  "termsofService":"http://www.wunderground.com/weather/api/d/terms.html",
  "features": {
  "conditions": 1
  }
    }
  , "current_observation": {
        "image": {
        "url":"http://icons.wxug.com/graphics/wu2/logo_130x80.png",
        "title":"Weather Underground",
        "link":"http://www.wunderground.com"
        },
        "display_location": {
        "full":"Kearney, MO",
        "city":"Kearney",
        "state":"MO",
        "state_name":"Missouri",

我不确定它是否对您有用,但我会将我的JSON发布到XML程序。

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     string     `xml:"current_observation>display_location>full"`
    StateName string        `xml:"current_observation>display_location>state_name"`
    WindGust string     `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"`;
    CurrentObservation map[string]map[string]string `json:"current_observation"`

}
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 := "Nunna"
    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.CurrentObservation = map[string]map[string]string {
        "display_location": map[string]string {
            "full": report.Full,
            "state_name": report.StateName,
        },"observation_location":map[string]string {"full": 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())
    }


}
//OUTPUT:
//JSON output nicely formatted: 
//{
//     "version": "0.1",
//      "termsofService": "http://www.wunderground.com/weather/api/d/terms.html",
//      "features": {
//            "feature": "conditions"
//      },
//      "current_observation": {
//            "display_location": {
//                  "full": "Kearney, MO",
//                  "state_name": "Missouri"
//            },
//            "observation_location": {
//                  "full": "HOMESTEAD HILLS, Kearney, Missouri"
//            }
//      }
//}

1 个答案:

答案 0 :(得分:0)

这与进入另一个方向的过程相同。定义结构/对象以对输入进行建模(在本例中为json),创建方法以将结构中的所有值分配给您用于输出的输入,然后封送输出以获取字符串。因此,为了使用您输入的一个概念上较难的字段给出一个练习示例,将一些json解组为reportTypeJson的实例,我可以将其分配给用于模拟xml的reportType,如此;

report.StateName = jsonReport.CurrentObservation["display_location"]["state_name"]

这里最大的区别是代表你的xml的结构是扁平的(就像它有Something> InnerSomething> InnerInnerSomething来表示它的嵌套值,而golang中的结构没有嵌套),与json一样,你在golang中的结构倾向于具有相同数量的嵌套(如具有map [string] map [string] [string]意味着项目嵌套在主结构内部的3个级别)。您可以通过访问字段时的间接量来观察这一点,例如上面的示例中,有一个级别的间接访问CurrentObservation但是这是一个映射的映射,因此我使用{进行索引{1}}生成display_location的密钥,因为我正在查找statename值,我必须使用map[string]string对其进行索引才能访问该值。

请注意,在实际程序中,需要进行大量检查,因为这些操作不安全。例如,如果json读取不包含state_name对象,则display_location将返回jsonReport.CurrentObservation["display_location"],并且尝试访问nil将导致恐慌。

另外,请注意,在您的程序中,我建议添加两个函数,一个名为["state_name",另一个名为NewJsonReport(report *reportType) *reportTypeJson, err,其中初始化/分配返回类型的新实例并返回它可以避免代码重复并使您的程序NewXmlReport(report *reportTypeJson) *reportType, err更具可读性。在程序中的多个位置进行这种类型的分配是笨重的编码,这会增加很多维护成本,并且很可能导致错误(例如,如果其中一个模型上的某些内容发生变化或者您需要输入在整个程序中修复对它的每一个引用,而不仅仅是更新我上面提到的函数。)