第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

使用動態(tài)鍵解組 JSON

使用動態(tài)鍵解組 JSON

Go
月關(guān)寶盒 2022-12-19 21:15:53
我有一個場景,其中 JSON 具有需要解組到結(jié)構(gòu)中的動態(tài)字段集。const jsonStream = `{    "name": "john",    "age": 23,    "bvu62fu6dq": {        "status": true    }}`type Status struct {    Status bool}type Person struct {    Name   string            `json:"name"`    Age    int               `json:"age"`    Status map[string]Status `json:"status"`}func main() {    dec := json.NewDecoder(strings.NewReader(jsonStream))    for {        var person Person        if err := dec.Decode(&person); err == io.EOF {            break        } else if err != nil {            log.Fatal(err)        }        fmt.Println(person)        fmt.Println(person.Status["bvu62fu6dq"])    }}輸出:{john 23 map[]}{false}當它被解組時,嵌套狀態(tài)結(jié)構(gòu)沒有被正確解析為 JSON 中的值(即使在 JSON 中顯示為真值也顯示為 false),代碼中是否有任何問題?
查看完整描述

2 回答

?
慕妹3146593

TA貢獻1820條經(jīng)驗 獲得超9個贊

您的類型與您擁有的 JSON 不匹配:


type Status struct {

    Status bool

}


type Person struct {

    Name   string            `json:"name"`

    Age    int               `json:"age"`

    Status map[string]Status `json:"status"`

}

映射到 JSON,看起來像這樣:


{

    "name": "foo",

    "age": 12,

    "status": {

        "some-string": {

            "Status": true

        }

    }

}

在 go 類型中使用已知/未知字段的組合來解組數(shù)據(jù)的最簡單方法是使用如下內(nèi)容:


type Person struct {

    Name   string                 `json:"name"`

    Age    int                    `json:"age"`

    Random map[string]interface{} `json:"-"` // skip this key

}

然后,首先解組已知數(shù)據(jù):


var p Person

if err := json.Unmarshal([]byte(jsonStream), &p); err != nil {

    panic(err)

}

// then unmarshal the rest of the data

if err := json.Unmarshal([]byte(jsonStream), &p.Random); err != nil {

    panic(err)

}

現(xiàn)在Random地圖將包含所有數(shù)據(jù),包括name和age字段。看到你已經(jīng)在結(jié)構(gòu)上標記了那些,這些鍵是已知的,所以你可以輕松地從地圖中刪除它們:


delete(p.Random, "name")

delete(p.Random, "age")

現(xiàn)在p.Random將包含所有未知鍵及其各自的值。這些值顯然將是一個帶有 field 的對象status,它應(yīng)該是一個布爾值。您可以著手使用類型斷言并將它們?nèi)哭D(zhuǎn)換為更合理的類型,或者您可以采取快捷方式并編組/取消編組值。像這樣更新你的Person類型:


type Person struct {

    Name     string                 `json:"name"`

    Age      int                    `json:"age"`

    Random   map[string]interface{} `json:"-"`

    Statuses map[string]Status      `json:"-"`

}

現(xiàn)在獲取干凈的Random值,將其編組并將其解組回Statuses字段中:


b, err := json.Marshal(p.Random)

if err != nil {

    panic(err)

}

if err := json.Unmarshal(b, &p.Statuses); err != nil {

    panic(err)

}

// remove Random map

p.Random = nil

結(jié)果Person.Statuses["bvu62fu6dq"].Status設(shè)置為true

清理這一切,并將數(shù)據(jù)編組回來


現(xiàn)在,因為我們的Random和Statuses字段被標記為在 JSON 編組 ( json:"-") 中被忽略,當您想從這些類型輸出原始 JSON 時,編組這種Person類型不會很好。最好將此邏輯包裝在自定義 JSON (un)-Marshaller 接口中。您可以在類型的MarshalJSON和UnmarshalJSON方法中使用一些中間類型Person,或者只創(chuàng)建一個映射并設(shè)置您需要的鍵:


func (p Person) MarshalJSON() ([]byte, error) {

    data := make(map[string]interface{}, len(p.Statuses) + 2) // 2 being the extra fields

    // copy status fields

    for k, v := range p.Statuses {

        data[k] = v

    }

    // add known keys

    data["name"] = p.Name

    data["age"] = p.Age

    return json.Marshal(data) // return the marshalled map

}

同樣,您可以為 做同樣的事情UnmarshalJSON,但您需要創(chuàng)建一個Person沒有自定義處理的類型版本:


type intermediaryPerson struct {

    Name string  `json:"name"`

    Age  int `json:"age"`

    Random map[string]interface{} `json:"-"`

}


// no need for the tags and helper fields anymore

type Person struct {

    Name    string

    Age     int

    Statuses map[string]Status // Status type doesn't change

}


func (p *Person) UnmarshalJSON(data []byte) error {

    i := intermediaryPerson{}

    if err := json.Unmarshal(data, &i); err != nil {

        return err

    }

    if err := json.Unmarshal(data, &i.Random); err != nil {

        return err

    }

    delete(i.Random, "name")

    delete(i.Random, "age")

    stat, err := json.Marshal(i.Random)

    if err != nil {

        return err

    }

    // copy known fields

    p.Name = i.Name

    p.Age = i.Age

    return json.Unmarshal(stat, &p.Statuses) // set status fields

}

在這種情況下,創(chuàng)建一個處理已知字段的類型并將其嵌入是很常見的,不過:


type BasePerson struct {

    Name string `json:"name"`

    Age  int    `json:"age"`

}

并將其嵌入中介和“主要”/導出類型中:


type interPerson struct {

   BasePerson

   Random map[string]interface{} `json:"-"`

}


type Person struct {

    BasePerson

    Statuses map[string]Status

}

這樣,您可以直接將已知字段解組為BasePerson類型,分配它,然后處理映射:


func (p *Person) UnmarshalJSON(data []byte) error {

    base := BasePerson{}

    if err := json.Unmarshal(data, &base); err != nil {

        return err

    }

    p.BasePerson = base // takes care of all known fields

    unknown := map[string]interface{}{}

    if err := json.Unmarshal(data, unknown); err != nil {

        return err

    }

    // handle status stuff same as before

    delete(unknown, "name") // remove known fields

    // marshal unknown key map, then unmarshal into p.Statuses

}

演示 2

這就是我的處理方式。它允許調(diào)用json.Marshal和json.Unmarshal看起來就像任何其他類型,它將未知字段的處理集中在一個地方(編組器/解組器接口的實現(xiàn)),并為您留下一個Person類型,其中每個字段都包含所需的數(shù)據(jù), 以可用的格式。它的效率有點低,因為它依賴于對未知密鑰的解組/編組/解組。你可以取消它,就像我說的那樣,使用類型斷言并在地圖上迭代,unknown而是用這樣的東西來解決:


for k, v := range unknown {

    m, ok := v.(map[string]interface{})

    if !ok {

        continue // not {"status": bool}

    }

    s, ok := m["status"]

    if !ok {

        continue // status key did not exist, ignore

    }

    if sb, ok := s.(bool); ok {

        // ok, we have a status bool value

        p.Statuses[k] = Status{

            Status: sb,

        }

    }

}

但說實話,性能差異不會那么大(這是微優(yōu)化 IMO),而且代碼對我來說有點太冗長了。懶惰,在需要時優(yōu)化,而不是隨時優(yōu)化


查看完整回答
反對 回復(fù) 2022-12-19
?
翻過高山走不出你

TA貢獻1875條經(jīng)驗 獲得超3個贊

類型不符合您的 json 值。


    const jsonStream = `{

    "name": "john",

    "age": 23,

    "bvu62fu6dq": {

        "status": true

     }

   }`

對于上面的 json,您的代碼應(yīng)該像下面的 snnipet 一樣工作(對現(xiàn)有代碼進行一些修改)。


package main


import (

    "encoding/json"

    "fmt"

    "io"

    "log"

    "strings"

)


const jsonStream = `{

    "name": "john",

    "age": 23,

    "bvu62fu6dq": {

        "status": true

    }

}`


type bvu62fu6dq struct {

    Status bool

}


type Person struct {

    Name   string     `json:"name"`

    Age    int        `json:"age"`

    Status bvu62fu6dq `json:"bvu62fu6dq"`

}


func main() {

    dec := json.NewDecoder(strings.NewReader(jsonStream))

    for {

        var person Person

        if err := dec.Decode(&person); err == io.EOF {

            break

        } else if err != nil {

            log.Fatal(err)

        }

        fmt.Println(person)

        fmt.Println(person.Status)

    }

}

根據(jù)您的 json 數(shù)據(jù),您必須使用類型字段進行映射。 運行代碼片段


查看完整回答
反對 回復(fù) 2022-12-19
  • 2 回答
  • 0 關(guān)注
  • 125 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學習伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號