2016-05-04 23 views
0

私はXMLからJSONへの変換について多くの記事を見てきましたが、最近これを行うプログラムを書いていますが、JSONからXMLに変換する方法についても興味がありました?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", 

私はそれはあなたにどんな使用するだろうかどうかわからないんだけど、私はXMLプログラムに私のJSONを投稿します。

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" 
//   } 
//  } 
//} 
+0

仕様をコードよりもはるかに興味深いものにするでしょう。 JSONをある種のXMLに変換するのは簡単です。 「通常の」ケースで使用できない結果を生成することなく、エッジケース(XMLで有効でない文字を含むJSONなど)を処理できる変換を設計することが課題です。 –

答えて

0

これは、他の方向に進むのと同じプロセスです。入力をモデリングするための構造体/オブジェクトを定義する(この場合はjson)、出力に使用している構造体への入力をモデリングする構造体からすべての値を割り当てるメソッドを作成し、出力をマーシャリングして文字列を取得する。だからあなたが入力したより概念的に難しいフィールドの1つを使って練習例を与えるには、reportTypeJsonのインスタンスにいくつかのjsonをアンマーシャリングして、reportTypeに割り当てることができます。

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

は、最大の違いは、ここでは、JSONのように、あなたの構造(それが何かを> InnerSomething> golang中のstructは何のネストを持っていない間、それは値を入れ子になっています表すためにInnerInnerSomething持っているよう)あなたのxmlを表す構造体が平坦ですgolangの中で同じ大きさのネスティングを持つ傾向があります(map [string] map [string] [string]という意味です)。上記の例のようにフィールドにアクセスすると、間接参照の量でこれを見ることができます。CurrentObservationにアクセスする間接レベルが1つありますが、それはマップのマップなので、display_locationキーを使用してそのインデックスにインデックスを付けます。 map[string]string、私はstatenameの値を探しているので、その値にアクセスするにはstate_nameでインデックスを付けなければなりません。

実際のプログラムでは、これらの操作が安全でないため、多数のチェックが必要であることに注意してください。たとえば、jsonの読み込みにdisplay_locationオブジェクトが含まれていなかった場合、jsonReport.CurrentObservation["display_location"]nilを返し、["state_name"にアクセスしようとするとパニックになります。

また、あなたのプログラムでは、NewJsonReport(report *reportType) *reportTypeJson, errと、NewXmlReport(report *reportTypeJson) *reportType, errと呼ばれる2つの関数を追加することをお勧めします。この場合、戻り値の型を初期化/あなたのプログラムmainをより読みやすくする。プログラム内の複数の場所でこのタイプの割り当てを行うことは、保守コストがかかり、行のバグが発生する可能性があるコードが不適切なコーディングです(モデルのいずれかが変更された場合や入力が必要な場合など)。上記の関数を更新するのではなく、プログラム全体を通してすべての参照を修正してください)。