2016-05-04 2 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", 

Я не уверен, если это было бы любое использование для вас, но я выложу мой 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" 
//   } 
//  } 
//} 
+0

Было бы гораздо интереснее видеть спецификацию, чем код. Преобразование JSON в какой-то XML является тривиальным; задача заключается в разработке преобразования, которое способно обрабатывать граничные случаи (например, JSON, содержащие символы, которые недопустимы в XML), не производя непригодных результатов в «обычных» случаях. –

ответ

0

Это тот же процесс, что и в другом направлении. Определите структуры/объекты для моделирования ввода (в данном случае это json), создайте метод, чтобы назначить все значения из структуры, моделирующей входные данные, тому, который вы используете для вывода, а затем маршалируйте вывод, чтобы получить строку. Поэтому, чтобы привести пример практики, используя один из более концептуально сложных полей из вашего типа, не подвергая сомнению некоторый json в экземпляр reportTypeJson, я могу назначить reportType, используемому для моделирования xml;

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

Самая большая разница здесь является структура, отображающая XML является плоской (как это имеет что-то> InnerSomething> InnerInnerSomething представлять это вложенные значения в то время как структура в golang не имеет вложенности), где, как и с JSON, ваши структуры в golang имеют тенденцию иметь такое же количество вложенности (например, наличие карты [string] map [string] [string], означающей, что элементы вложены в 3 уровня внутри основной структуры). Вы можете наблюдать это по объему косвенности при доступе к полям, как в приведенном выше примере, существует один уровень косвенности для доступа к CurrentObservation, но это карта карт, поэтому я индексирую его с помощью ключа 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, в которой вы инициализируете/выделяете новый экземпляр возвращаемого типа и возвращаете его, чтобы избежать дублирования кода и сделайте ваши программы main более читаемыми. Выполнение этого типа назначения в нескольких местах в программе - это неаккуратное кодирование, которое добавит много затрат на обслуживание и, вероятно, приведет к ошибкам в строке (например, если что-то изменится на одной из моделей или на вход, который у вас есть исправить каждую ссылку на нее в течение всей программы, а не просто обновлять перечисленные выше функции).

Смежные вопросы