欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Go解析不定JSON數(shù)據(jù)的方法詳解

 更新時間:2024年03月10日 08:21:22   作者:安妮的心動錄  
在開發(fā)中常常會碰到很多JSON類型的數(shù)據(jù)進行交互,而其中有很多JSON數(shù)據(jù)你是不能確定它的字段和結(jié)構(gòu)的,而Go語言是一門靜態(tài)強類型的語言,在進行JSON解析的時候必須要確定字段的類型,本文給大家介紹了Go如何解析不定JSON數(shù)據(jù),需要的朋友可以參考下

前言

在開發(fā)中常常會碰到很多JSON類型的數(shù)據(jù)進行交互,而其中有很多JSON數(shù)據(jù)你是不能確定它的字段和結(jié)構(gòu)的,而Go語言是一門靜態(tài)強類型的語言,在進行JSON解析的時候必須要確定字段的類型,定義出對應(yīng)的結(jié)構(gòu)體,然后再進行Unmarshal,那這二者之間的沖突我們該如何解決呢?

什么是JSON

  • json是JavaScript Object Notation(JavaScript對象表示法)
  • json是輕量級的文本數(shù)據(jù)交換格式
  • json獨立于語言
  • json具有自我描述性,更容易理解
  • json使用js語法來描述數(shù)據(jù)對象,但是json仍然獨立于語言和平臺,json解析器和json庫支持許多不同的編程語言

json是一種輕量級的數(shù)據(jù)交換格式,易于人閱讀和編寫,同時也易于機器解析和生成,之所以json這么流行,是因為json的結(jié)構(gòu)和多級結(jié)構(gòu)體(對象)剛好能對應(yīng)上,并且本身也十分易讀。而前后端交互的時候后端通常會返回給前端一個多級的結(jié)構(gòu)體,于是json慢慢開始流行了,且json是跨語言和跨平臺的,自身也足夠輕量級。

json的幾種標(biāo)準格式

一個標(biāo)準的json數(shù)據(jù)
//每個key對應(yīng)的是一個value
{
“k1": 1,
"k2": 2 //注意結(jié)尾的這個不能有逗號
}



json字符串
{
"k1": "1",
"k2": "2"
}


json數(shù)組
{
“k1”: [1,2],
“k2”: [3,4]
}


json對象
{
“k1”: {“1”: “haihai”},
“k2”: {“2”:”haihahai”}
}


json對象數(shù)組
{
“k1”: [
{“k11”: “hellohello”},
{“k12”: “badbad”}
]
}



json數(shù)組對象
{
“k2”: {
	“hello”: [1,2,3]
	}
}

所有的JSON數(shù)據(jù)都是由上述幾種JSON數(shù)據(jù)組合而成

如何在Go中解析不確定的JSON數(shù)據(jù)

通過看文檔的方式去確定對應(yīng)的JSON數(shù)據(jù),然后構(gòu)造對應(yīng)的結(jié)構(gòu)體

這是最靠譜的方式,最合理也是效率最高的方式。

// 請求其他服務(wù)   
jsonStr := xxx

var data interface{}

err := json.Unmarshal([]byte(jsonStr),&data)

fmt.Println(data)

比如可以先拿一個interface{}類型來接住JSON數(shù)據(jù),然后看這個interface{}的值,來確定這個JSON數(shù)據(jù)哪些字段是string 哪些是object 哪些是int float等等
當(dāng)然這也不是完全適用的,比如下面這種情況,有一個字段如下
type : []
能看出來type是一個切片類型的值,但是具體的類型你并不知道,可能是[]int 也有可能是[]string []float等等

map[string] interface{}

這個類型是map鍵值對,值可以是任意類型,因為在go中任意類型都實現(xiàn)了空接口interface{},而json數(shù)據(jù)也是key value的鍵值對,所以map[string] interface{}天然支持解析json類型數(shù)據(jù)

jsonStr := xxx
var data map[string]interface{} 
err := json.Unmarshal([]byte(jsonStr),&data)

// 你想取的字段
fieldValue := data["field"]

// 類型斷言
if value,ok := data["field"].(float64);ok {

} else if vluae,ok := data["field"].(int64); ok {

}

理論上所有的合法的JSON數(shù)據(jù)都可以被反序列化到map[string]interface{}中
但是實際應(yīng)用中 可能會出現(xiàn)一些無法被map[string]interface{}解析的JSON數(shù)據(jù)
  • JSON 數(shù)據(jù)中包含了多層嵌套的數(shù)據(jù)結(jié)構(gòu)。在這種情況下,如果沒有使用遞歸或者其他方式對嵌套數(shù)據(jù)進行處理,可能會導(dǎo)致反序列化失敗。
  • JSON 數(shù)據(jù)中包含了數(shù)組類型,但是數(shù)組元素類型不一致或者無法轉(zhuǎn)換成相應(yīng)的類型。在這種情況下,可能需要手動處理數(shù)組元素或者使用其他數(shù)據(jù)類型來保存數(shù)組數(shù)據(jù)。
  • JSON 數(shù)據(jù)中包含了自定義數(shù)據(jù)類型或者復(fù)雜的數(shù)據(jù)結(jié)構(gòu),無法使用 map[string]interface{} 類型來反序列化。在這種情況下,需要定義相應(yīng)的結(jié)構(gòu)體或者使用其他適合的數(shù)據(jù)類型來反序列化。

第三方庫

除了encoding/json之外,還有很多第三方庫可以用來解析不確定的JSON數(shù)據(jù),例如gjson和jsonparser,這些庫通常提供了更加靈活和高效的JSON解析方式,可以根據(jù)具體的需求選擇合適的庫來使用

json.RawMessage與json.Number

  • json.RawMessage 是一個非常高效的數(shù)據(jù)類型,因為她不需要進行任何解析和類型轉(zhuǎn)換,直接保存了未經(jīng)處理的原始JSON數(shù)據(jù),在反序列化的時候只需要將json.RawMessage轉(zhuǎn)化為對應(yīng)的數(shù)據(jù)類型即可,無需重新解析JSON數(shù)據(jù)
  • json.Number 表示JSON中的數(shù)字類型,可以用來保存任意精度的數(shù)字。這個數(shù)字可以特別大,可能會無法用Go中的整數(shù)或者浮點數(shù)來表示
package main

import (
    "encoding/json"
    "fmt"
)

func main() {
    jsonData := []byte(`{
        "id": 12345,
        "name": "John Doe",
        "age": 30,
        "score": 95.5,
        "is_student": true,
        "tags": ["tag1", "tag2", "tag3"],
        "extra": {
            "field1": "value1",
            "field2": 123
        }
    }`)

    var m map[string]json.RawMessage
    err := json.Unmarshal(jsonData, &m)
    if err != nil {
        panic(err)
    }

    var id int
    err = json.Unmarshal(m["id"], &id)
    if err != nil {
        panic(err)
    }
    fmt.Printf("id: %d\n", id)

    var name string
    err = json.Unmarshal(m["name"], &name)
    if err != nil {
        panic(err)
    }
    fmt.Printf("name: %s\n", name)

    var age int
    err = json.Unmarshal(m["age"], &age)
    if err != nil {
        panic(err)
    }
    fmt.Printf("age: %d\n", age)

    var score float64
    err = json.Unmarshal(m["score"], &score)
    if err != nil {
        panic(err)
    }
    fmt.Printf("score: %f\n", score)

    var isStudent bool
    err = json.Unmarshal(m["is_student"], &isStudent)
    if err != nil {
        panic(err)
    }
    fmt.Printf("is_student: %v\n", isStudent)

    var tags []string
    err = json.Unmarshal(m["tags"], &tags)
    if err != nil {
        panic(err)
    }
    fmt.Printf("tags: %v\n", tags)

    var extra map[string]json.RawMessage
    err = json.Unmarshal(m["extra"], &extra)
    if err != nil {
        panic(err)
    }
    var field1 string
    err = json.Unmarshal(extra["field1"], &field1)
    if err != nil {
        panic(err)
    }
    fmt.Printf("extra.field1: %s\n", field1)

    var field2 int
    err = json.Unmarshal(extra["field2"], &field2)
    if err != nil {
        panic(err)
    }
    fmt.Printf("extra.field2: %d\n", field2)
}

// 不確定的類型
data := make(map[string]interface{})
if err := json.Unmarshal(rawData, &data); err != nil {
    log.Fatal(err)
}

if value, ok := data["age"].(float64); ok {
    // 處理年齡為浮點數(shù)的情況
} else if value, ok := data["age"].(int); ok {
    // 處理年齡為整數(shù)的情況
} else {
    // 處理年齡為其他類型或不存在的情況
}

需要注意的是:類型斷言的底層為反射,因為在運行時需要判斷一個接口值的具體類型,而這個類型是在編譯時無法確定的,需要在運行時動態(tài)地獲取。效率比正常的代碼低一到兩個數(shù)量級,而且需要消耗額外的時間和內(nèi)存。

最后

以上就是Go解析不定JSON數(shù)據(jù)的方法詳解的詳細內(nèi)容,更多關(guān)于Go解析不定JSON數(shù)據(jù)的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Golang標(biāo)準庫os/exec執(zhí)行外部命令并獲取其輸出包代碼示例

    Golang標(biāo)準庫os/exec執(zhí)行外部命令并獲取其輸出包代碼示例

    這篇文章主要為大家介紹了Golang標(biāo)準庫os/exec執(zhí)行外部命令并獲取其輸出包代碼示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-12-12
  • Golang字符串常用函數(shù)的使用

    Golang字符串常用函數(shù)的使用

    Golang提供了許多內(nèi)置的字符串函數(shù),這些函數(shù)可在處理字符串?dāng)?shù)據(jù)時幫助執(zhí)行一些操作,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • Golang算法問題之?dāng)?shù)組按指定規(guī)則排序的方法分析

    Golang算法問題之?dāng)?shù)組按指定規(guī)則排序的方法分析

    這篇文章主要介紹了Golang算法問題之?dāng)?shù)組按指定規(guī)則排序的方法,結(jié)合實例形式分析了Go語言數(shù)組排序相關(guān)算法原理與操作技巧,需要的朋友可以參考下
    2017-02-02
  • Go中g(shù)routine通信與context控制實例詳解

    Go中g(shù)routine通信與context控制實例詳解

    隨著context包的引入,標(biāo)準庫中很多接口因此加上了context參數(shù),下面這篇文章主要給大家介紹了關(guān)于Go中g(shù)routine通信與context控制的相關(guān)資料,需要的朋友可以參考下
    2022-02-02
  • 使用Go語言開發(fā)短鏈接服務(wù)的方法

    使用Go語言開發(fā)短鏈接服務(wù)的方法

    短鏈接一般是通過映射關(guān)系,將長長的一串網(wǎng)址,映射到幾個字符的短鏈接上,建立好這種映射關(guān)系之后保存到數(shù)據(jù)庫里,用戶每次訪問短鏈接的時候,這篇文章主要介紹了使用Go語言開發(fā)一個短鏈接服務(wù),需要的朋友可以參考下
    2024-03-03
  • 詳解如何使用Golang操作MongoDB數(shù)據(jù)庫

    詳解如何使用Golang操作MongoDB數(shù)據(jù)庫

    在現(xiàn)代開發(fā)中,數(shù)據(jù)存儲是一個至關(guān)重要的環(huán)節(jié),MongoDB作為一種NoSQL數(shù)據(jù)庫,提供了強大的功能和靈活的數(shù)據(jù)模型,與Golang的高性能和并發(fā)性能非常契合,本文將探討Golang與MongoDB的完美組合,介紹如何使用Golang操作MongoDB數(shù)據(jù)庫,需要的朋友可以參考下
    2023-11-11
  • Go日志框架zap增強及源碼解讀

    Go日志框架zap增強及源碼解讀

    這篇文章主要為大家介紹了Go日志框架zap增強及源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-07-07
  • golang連接kafka消費進ES操作

    golang連接kafka消費進ES操作

    這篇文章主要介紹了golang連接kafka消費進ES操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • golang coroutine 的等待與死鎖用法

    golang coroutine 的等待與死鎖用法

    這篇文章主要介紹了golang coroutine 的等待與死鎖用法詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-05-05
  • Golang 刪除文件并遞歸刪除空目錄的操作

    Golang 刪除文件并遞歸刪除空目錄的操作

    這篇文章主要介紹了Golang 刪除文件并遞歸刪除空目錄的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04

最新評論