亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

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

如何將 JSON 對象數組轉換為 Go 中具有默認值的結構數組?

如何將 JSON 對象數組轉換為 Go 中具有默認值的結構數組?

Go
桃花長相依 2021-11-15 15:49:26
我正在開發一個 Go API,它可以接收由 JSON 對象數組組成的 POST。POST 的結構類似于:[  {    "name":"Las Vegas",    "size":14  },  {    "valid": false,    "name":"Buffalo",    "size":63  }]  假設我有以下結構:type Data {    Valid    bool    Name     string    Size     float64}我想創建一堆Datas 并Valid設置為true任何時候它實際上并未在 JSON 中指定為false. 如果我只做一個,我可以在 Go 中解析 JSON 時使用如何指定默認值,但是對于未知數量的它們,我唯一能想到的是:var allMap []map[string]interface{}var structs []Datafor _, item := range allMap {  var data Data  var v interface{}  var ok bool  if v, ok := item["value"]; ok {    data.Valid = v  } else {    data.Valid = true  }  id v, ok := item["name"]; ok {    data.Name = v  }  ...  structs = append(structs, data)}return structs現在我實際使用的結構有 14 個字段,其中一些具有我想分配默認值的值,其他的可以留空,但所有這些都必須使用這種方法進行迭代。有沒有更好的辦法?
查看完整描述

2 回答

?
九州編程

TA貢獻1785條經驗 獲得超4個贊

您可以使用該json.RawMessage類型來推遲解組某些 JSON 文本值。如果您使用這種類型,那么 JSON 文本將存儲在其中而無需解組(因此您可以稍后根據需要解組此片段)。


因此,在您的情況下,如果您嘗試解組成一個這樣的切片RawMessage,您可以使用您在問題中鏈接的技術,即您可以迭代原始值的切片(每個值的 JSON 文本Data),創建一個Datastruct 將您想要的值作為缺失值的默認值,并將切片元素解組到這個準備好的結構中。就這樣。


它看起來像這樣:


allJson := []json.RawMessage{}

if err := json.Unmarshal(src, &allJson); err != nil {

    panic(err)

}


allData := make([]Data, len(allJson))

for i, v := range allJson {

    // Here create your Data with default values

    allData[i] = Data{Valid: true}

    if err := json.Unmarshal(v, &allData[i]); err != nil {

        panic(err)

    }

}

在Go Playground上試一試。


注釋/變體


為了提高效率(為了避免復制結構體),您還allData可以在上面的示例中使成為一個指針切片,如下所示:


allData := make([]*Data, len(allJson))

for i, v := range allJson {

    // Here create your Data with default values

    allData[i] = &Data{Valid: true}

    if err := json.Unmarshal(v, allData[i]); err != nil {

        panic(err)

    }

}

如果您想繼續使用非指針,為了提高效率,您可以在切片元素本身中“準備”您想要的默認值,如下所示:


allData := make([]Data, len(allJson))

for i, v := range allJson {

    // Here set your default values in the slice elements

    // Only set those which defer from the zero values:

    allData[i].Valid = true

    if err := json.Unmarshal(v, &allData[i]); err != nil {

        panic(err)

    }

}


查看完整回答
反對 回復 2021-11-15
?
白衣染霜花

TA貢獻1796條經驗 獲得超10個贊

您可以通過UnmarshalJSON在您的類型上提供一種方法來使其透明并自動工作,即使您的類型在結構或切片中找到,您也可以做一個很好的技巧。


func (d *Data) UnmarshalJSON(j []byte) error {

    type _Data Data // Dummy type to avoid infinite recursion in UnmarshalJSON

    tmp := _Data{ // Set defaults here

        Valid: true,

    }


    err := json.Unmarshal(j, &tmp)

    if err != nil {

        return err

    }


    *d = Data(tmp)

    return nil

}

類型的_Data存在只是為了讓我們可以調用json.Unmarshal(j, &tmp)并獲得原始的未覆蓋行為,而不是調用UnmarshalJSON我們已經在中間的方法。我們可以tmp使用您已經鏈接到的技巧設置默認值。然后在解組完成后,我們可以轉換tmp為,Data因為畢竟Data和_Data確實是相同的類型。


鑒于這種方法,您可以簡單地


var structs []Data

err := json.Unmarshal(input, &structs)

(或同樣使用 a json.Decoder)并讓它按照您想要的方式工作。


查看完整回答
反對 回復 2021-11-15
  • 2 回答
  • 0 關注
  • 416 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號