天天看點

go不定義結構體解析json背景simplejson庫Interface{}怎麼轉換成string?

go不定義結構體解析json

  • 背景
  • simplejson庫
  • Interface{}怎麼轉換成string?

背景

系統自帶的 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":"成功"
}
           

解決思路:

  1. 通過 map[string]interface{}
  2. 使用反射和Interface,開源庫simplejson就是這樣幹的。https://github.com/bitly/go-simplejson

這裡使用simplejson去做。

simplejson庫

https://godoc.org/github.com/bitly/go-simplejson

1.import

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))
}