Golang解析json的特殊情況處理

Go解析json遇到了大數(shù)字窟社、不定格式等特殊情況,在此做了一個整理绪钥。

Unmarshal vs Decode

選擇哪個要視輸入而定灿里。

json.Unmarshal 操作對象是一個 []byte,也就意味著被處理的JSON要全部加載到內(nèi)存程腹。如果有一個加載完的JSON使用json.Unmarshal會快一些匣吊。

json.Decoder 操作的是一個stream,或者其他實現(xiàn)了io.Reader接口的類型跪楞。意味著可以在接收或傳輸?shù)耐瑫r對其進行解析缀去。當處理一組較大數(shù)據(jù)時無需重新copy整個JSON到內(nèi)存中侣灶。

最好的選擇辦法如下:

  • 如果數(shù)據(jù)來自一個io.Reader或者需要從一個stream中讀取數(shù)據(jù)甸祭,就選擇json.Decoder
  • 如果已經(jīng)將整個JSON加載到內(nèi)存中了就使用json.Unmarshal

數(shù)字的解析

默認情況下,go對json解析過程中遇到的數(shù)字都會當做float64處理褥影。如果數(shù)字過大會有精度丟失池户。可以使用json.Number來處理凡怎。

Unmarshal

val := `{"id": 100010001000100010001000 }` //26位數(shù)字
var y map[string]json.Number
json.Unmarshal([]byte(val), &y)
fmt.Println(y) //map[id:100010001000100010001000]

z, _ := json.Marshal(struct {
    Id json.Number `json:"id"`
}{y["id"]})
fmt.Println(string(z)) //{"id":100010001000100010001000}

Decode

val := `{"id": 100010001000100010001000 }` //26位數(shù)字
val2 := strings.NewReader(val)             //先轉成io.Reader
d := json.NewDecoder(val2)
d.UseNumber() //標記使用josn.Number

var x map[string]interface{}
if err := d.Decode(&x); err != nil {
    panic(err)
}
fmt.Printf("%#v\n", x) //相應值的Go語法表示

newJson, _ := json.Marshal(x)
fmt.Println(string(newJson)) //json.Number編組結果

輸出結果:

map[string]interface {}{"id":"100010001000100010001000"}
{"id":100010001000100010001000}

使用json.Decoder只能操作io.Reader類型的JSON數(shù)據(jù)校焦。

不定類型的解析

有時候遇到字段不定的JSON,需要一邊判斷一邊解析统倒。如:

t1 := `{"type":"a", id:"aaa"}`
t2 := `{"type":"b", id:22222}`

解組到interface{}

可以先統(tǒng)一解組到interface{} 然后判斷關鍵字段再進行后續(xù)處理寨典。

type Data struct {
    Type string      `json:"type"`
    Id   interface{} `json:"id"`
}

func decode(t string) {
    var x Data
    err := json.Unmarshal([]byte(t), &x)
    if err != nil {
        panic(err)
    }
    if x.Type == "a" {
        fmt.Println(x.Id.(string))
    } else {
        fmt.Println(x.Id.(float64)) //json解析中number默認作為float64解析
    }
}
func main() {
    t1 := `{"type":"a", "id":"aaa"}`
    t2 := `{"type":"b", "id":22222}`

    decode(t1)
    decode(t2)
}

結果

aaa
22222

使用json.RawMessage

使用RawMessage便于分步Unmarshal

type Resp struct {
    Type string          `json:"type"`
    Data json.RawMessage `json:"data"`
}
type Data struct {
    Id json.Number `json:"id"` //處理大數(shù)
}

func main() {
    t := `{"type": "a", "data":{"id": 1234567890123456789012345}}`

    var x Resp
    var y Data

    json.Unmarshal([]byte(t), &x)

    //進一步解組
    if "a" == x.Type {
        json.Unmarshal(x.Data, &y)
    }

    fmt.Println(y.Id)

    r, _ := json.Marshal(x)
    fmt.Println(string(r))
}

原文鏈接

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市房匆,隨后出現(xiàn)的幾起案子耸成,更是在濱河造成了極大的恐慌报亩,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,110評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件井氢,死亡現(xiàn)場離奇詭異弦追,居然都是意外死亡,警方通過查閱死者的電腦和手機花竞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評論 3 395
  • 文/潘曉璐 我一進店門劲件,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人约急,你說我怎么就攤上這事零远。” “怎么了烤宙?”我有些...
    開封第一講書人閱讀 165,474評論 0 356
  • 文/不壞的土叔 我叫張陵遍烦,是天一觀的道長。 經(jīng)常有香客問我躺枕,道長服猪,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,881評論 1 295
  • 正文 為了忘掉前任拐云,我火速辦了婚禮罢猪,結果婚禮上,老公的妹妹穿的比我還像新娘叉瘩。我一直安慰自己膳帕,他們只是感情好,可當我...
    茶點故事閱讀 67,902評論 6 392
  • 文/花漫 我一把揭開白布薇缅。 她就那樣靜靜地躺著危彩,像睡著了一般。 火紅的嫁衣襯著肌膚如雪泳桦。 梳的紋絲不亂的頭發(fā)上汤徽,一...
    開封第一講書人閱讀 51,698評論 1 305
  • 那天,我揣著相機與錄音灸撰,去河邊找鬼谒府。 笑死,一個胖子當著我的面吹牛浮毯,可吹牛的內(nèi)容都是我干的完疫。 我是一名探鬼主播,決...
    沈念sama閱讀 40,418評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼债蓝,長吁一口氣:“原來是場噩夢啊……” “哼壳鹤!你這毒婦竟也來了?” 一聲冷哼從身側響起饰迹,我...
    開封第一講書人閱讀 39,332評論 0 276
  • 序言:老撾萬榮一對情侶失蹤芳誓,失蹤者是張志新(化名)和其女友劉穎讯嫂,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體兆沙,經(jīng)...
    沈念sama閱讀 45,796評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡欧芽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,968評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了葛圃。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片千扔。...
    茶點故事閱讀 40,110評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖库正,靈堂內(nèi)的尸體忽然破棺而出曲楚,到底是詐尸還是另有隱情,我是刑警寧澤褥符,帶...
    沈念sama閱讀 35,792評論 5 346
  • 正文 年R本政府宣布龙誊,位于F島的核電站,受9級特大地震影響喷楣,放射性物質(zhì)發(fā)生泄漏趟大。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,455評論 3 331
  • 文/蒙蒙 一铣焊、第九天 我趴在偏房一處隱蔽的房頂上張望逊朽。 院中可真熱鬧,春花似錦曲伊、人聲如沸叽讳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽岛蚤。三九已至,卻和暖如春懈糯,著一層夾襖步出監(jiān)牢的瞬間涤妒,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評論 1 272
  • 我被黑心中介騙來泰國打工昂利, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留届腐,地道東北人铁坎。 一個月前我還...
    沈念sama閱讀 48,348評論 3 373
  • 正文 我出身青樓蜂奸,卻偏偏與公主長得像,于是被迫代替她去往敵國和親硬萍。 傳聞我的和親對象是個殘疾皇子扩所,可洞房花燭夜當晚...
    茶點故事閱讀 45,047評論 2 355