go不定义结构体解析json
背景
系统自带的 Json.Marshal / Json.Unmarshal 需要定义一个结构体,json比较简单的时候就很好用,对于以下复杂的类型,就不太合适
{
"userInfo":{
"userId":"100021",
"deviceCode":"1111"
},
"answerInfos":[
{
"question":"基价",
"standardQuestion":"查基价",
"questionId":"1452128",
"isHit":1,
"relatedQuestions":[
"基价"
],
"sessionId":"e455af0986d24c2daa2cdc50d62cec60",
"answerCoded":"您要看哪个城市?&{R_001_001|ctg:中厚板|time:}",
"answer":"您要看哪个城市?",
"isChart":0,
"chartId":"1434187",
"isContinuous":1,
"isLast":0,
"tips":[
"冷轧",
"热轧",
"中厚板",
"低合金"
],
"answerSource":"XIAO_I",
"expandInfo":{
"text":"查看更多",
"url":"http://baidu.com"
},
"isCard":1,
"cardCode":"CARD_001",
"cardInfo":"{"buttonName":"查看订单","cardCode":"CARD_001","cardName":"打开订单","loginCheck":1,"operationCode":"H5","operationValue":"http:我的订单","tips":["可以点击【我的订单】【申请提货】按钮提货","可以点击【我的订单】【申请提货】按钮提货"],"titleContext":"您可点击下方按钮进入【我的订单】页面进行提货"}"
}
],
"resCode":0,
"errorMsg":"成功"
}
解决思路:
- 通过 map[string]interface{}
- 使用反射和Interface,开源库simplejson就是这样干的。https://github.com/bitly/go-simplejson
这里使用simplejson去做。
simplejson库
https://godoc.org/github.com/bitly/go-simplejson
1.import
import "github.com/bitly/go-simplejson"
2.new
var j *simplejson.Json
j, err = simplejson.NewJson(data)
if err != nil {
logger.Sugar.Warnf("NewJson error:%s", err.Error())
return
}
3.此时就可以读取了
// 获取 answerInfos 节点
answerNode := j.Get("answerInfos")
// 节点是数组,没有名字,可用索引获取
node1 := answerNode.GetIndex(0)
// 获取question字段
q := node1.Get("question").MustString()
4.完整代码
package main
import (
"encoding/json"
"fmt"
"github.com/bitly/go-simplejson"
)
func main() {
data := []byte(`
{
"userInfo": {
"userId": "100021",
"deviceCode": "1111"
},
"answerInfos": [{
"question": "基价",
"standardQuestion": "查基价",
"questionId": "1452128",
"isHit": 1,
"relatedQuestions": [
"基价"
],
"sessionId": "e455af0986d24c2daa2cdc50d62cec60",
"answerCoded": "您要看哪个城市?&{R_001_001|ctg:中厚板|time:}",
"answer": "您要看哪个城市?",
"isChart": 0,
"chartId": "1434187",
"isContinuous": 1,
"isLast": 0,
"tips": [
"冷轧",
"热轧",
"中厚板",
"低合金"
],
"answerSource": "XIAO_I",
"expandInfo": {
"text": "查看更多",
"url": "http://baidu.com"
},
"isCard": 1,
"cardCode": "CARD_001",
"cardInfo": {
"buttonName": "查看订单",
"cardCode": "CARD_001",
"cardName": "打开订单",
"loginCheck": 1,
"operationCode": "H5",
"operationValue": "http:我的订单",
"tips": [
"可以点击【我的订单】【申请提货】按钮提货",
"可以点击【我的订单】【申请提货】按钮提货"
],
"titleContext": "您可点击下方按钮进入【我的订单】页面进行提货"
}
}],
"resCode": 0,
"errorMsg": "成功"
}
`)
var j *simplejson.Json
j, err := simplejson.NewJson(data)
if err != nil {
fmt.Print("NewJson error:", err.Error())
return
}
// 获取 answerInfos 节点
answerNode := j.Get("answerInfos")
// answerInfos 下面是一个数组
// rows是 []interface{},类型
rows, err := answerNode.Array()
if err != nil {
fmt.Print("Get answerInfos error:", err.Error())
return
}
// 打印answerInfos下数组长度,这里只有1个节点,所以是1
fmt.Printf("answerInfos size:%d \n", len(rows))
// row是interface{}类型
for index, row := range rows {
// rows是数组,所以需要再获取一下节点
node := answerNode.GetIndex(index)
question := node.Get("question").MustString()
answer := node.Get("answer").MustString()
fmt.Printf("q:%s,a:%s \n", question, answer)
// row是interface{}类型,可以调用系统方法,再转换成一段json
data, err := json.Marshal(row)
if err == nil {
fmt.Printf("answerInfos[%d]=%s", index, string(data))
}
}
}
输出
answerInfos size:1
q:基价,a:您要看哪个城市?
answerInfos[0]={"answer":"您要看哪个城市?","answerCoded":"您要看哪个城市?\u0026{R_001_001|ctg:中厚板|time:}","answerSource":"XIAO_I","cardCode":"CARD_001","cardInfo":{"buttonName":"查看订单","cardCode":"CARD_001","cardName":"perationCode":"H5","operationValue":"http:我的订单","tips":["可以点击【我的订单】【申请提货】按钮提货","可以点击【我的订单】【申请提货】按钮提货"],"titleContext":"您可点击下方按钮进入【我的订单】页面进行提货"},"chartId":"1434181,"isChart":0,"isContinuous":1,"isHit":1,"isLast":0,"question":"基价","questionId":"1452128","relatedQuestions":["基价"],"sessionId":"e455af0986d24c2daa2cdc50d62cec60","standardQuestion":"查基价","tips":["冷轧","热轧","中厚板","低合金"]}
Interface{}怎么转换成string?
类似下面的json,我如果只需要取 answerInfos[0],返回给前端怎么办?
"answerInfos": [{
"question": "基价",
"standardQuestion": "查基价",
"questionId": "1452128",
"isHit": 1,
"relatedQuestions": [
"基价"
],
"sessionId": "e455af0986d24c2daa2cdc50d62cec60",
"answerCoded": "您要看哪个城市?&{R_001_001|ctg:中厚板|time:}",
"answer": "您要看哪个城市?",
"isChart": 0,
"chartId": "1434187",
"isContinuous": 1,
"isLast": 0,
"tips": [
"冷轧",
"热轧",
"中厚板",
"低合金"
],
"answerSource": "XIAO_I",
"expandInfo": {
"text": "查看更多",
"url": "http://baidu.com"
},
"isCard": 1,
"cardCode": "CARD_001",
"cardInfo": {
"buttonName": "查看订单",
"cardCode": "CARD_001",
"cardName": "打开订单",
"loginCheck": 1,
"operationCode": "H5",
"operationValue": "http:我的订单",
"tips": [
"可以点击【我的订单】【申请提货】按钮提货",
"可以点击【我的订单】【申请提货】按钮提货"
],
"titleContext": "您可点击下方按钮进入【我的订单】页面进行提货"
}
}],
答案:使用 simplejson.GetIndex() + json.Marshal() 即可
// 这是Interface{}类型
node := answerNode.GetIndex(index)
// row是interface{}类型,可以调用系统方法,再转换成一段json
data, err := json.Marshal(row)
if err == nil {
fmt.Printf("answerInfos[%d]=%s", index, string(data))
}