起因
某个上古时代的API,依然在返回XML格式的数据,更奇葩的是,GBK格式的。
用Go顺利的写到了发送数据,接收数据,然后取值有点麻烦啊。。。。
各种Google后,终于解决,但是不保证是唯一,正确,最合适的答案。
说在前边
本文假设要解析的XMl数据为:
<?xml version="1.0" encoding="GBK" ?>
<response>
<status>200</status>
</response>
要解决的问题是取出“200”这个状态值。
导入包
解析XML使用了”encoding/xml”这个包。
所以先导入这个包。
import "encoding/xml"
定义struct
定义一个自定义类型的Response
type Response struct {
Status int `xml:"status" json:"status"`
}
定义一个Response类型的变量
var result Response
偷懒转格式
因为”encoding/xml”不支持GBK格式的XML,而返回的内容又固定标明了编码是GBK,所以这里偷懒,直接把GBK替换成UTF-8,本例中不影响结果。
xmlstr := `?xml version="1.0" encoding="GBK" ?>
<response>
<status>200</status>
</response>
`
xmlstr = strings.Replace(xmlstr, "GBK", "UTF-8", -1)
使用strings包,替换“GBK”,相信根据参数顺序能看出各个参数的意义,最后一个参数:-1,为替换全部,即字符串中所有出现的第二个参数全部替换。
解析,转换,取值
使用encoding/jon,go-simplejson包
//解析XML
err := xml.Unmarshal([]byte(xmlstr), &result)
if nil != err {
log.Fatal(err)
}
log.Printf("XML:%v \n", result)
//转换成JSON
res, err := json.Marshal(result)
if nil != err {
log.Fatal(err)
}
log.Printf("JSON:%s \n", res)
js, err := simplejson.NewJson([]byte(res))
if nil != err {
log.Fatal(err)
}
status, err := js.Get("status").Int()
log.Printf("STATUS:%v \n", status)
以上是本人在处理XML 转 JSON 时的解决办法,应该还有更简单更合适的方案。仅供参考。
完整代码:
package main
import (
"encoding/xml"
"encoding/json"
"log"
"strings"
simplejson "github.com/bitly/go-simplejson"
)
type Response struct {
Status int `xml:"status" json:"status"`
}
func main() {
var result Response
//多行字符串,使用反引号`
xmlstr := `<?xml version="1.0" encoding="GBK" ?>
<response>
<status>200</status>
</response>`
xmlstr = strings.Replace(xmlstr, "GBK", "UTF-8", -1)
err := xml.Unmarshal([]byte(xmlstr), &result)
if err != nil {
log.Fatal(err)
}
log.Printf("XML:%v",result)
r, err := json.Marshal(result)
if nil != err {
log.Fatal(err)
}
log.Printf("JSON:%s", r)
js, err := simplejson.NewJson([]byte(r))
if nil != err {
log.Fatal(err)
}
status, err := js.Get("status").Int()
log.Printf("VALUE:%v",status)
}
发现问题:
今天(2016-09-18),再看这段代码,发现跟另一个程序里有些不一样。
另一个程序里是这样的:
type Response struct {
Status int `xml:"status"
}
也可以正常返回值,但是在本文中的示例却不能正常输出status值,而是会输出空,看了半天发现,使用 log 时:
log.Printf("VALUE:%v",status)
如果struct没有写 “json:“status””,就不能输出,如果换成fmt,struct就可以不写“json:“status”。结果是一样的,其中的原因还要再查资料研究下。
参考文章:
https://play.golang.org/p/7HNLEUnX-m