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

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

慣用的 JSON 對象數組 -> map[string]json.RawMessage

慣用的 JSON 對象數組 -> map[string]json.RawMessage

Go
不負相思意 2022-12-19 20:02:51
我正在嘗試解組 HTTP REST API 請求的結果,該請求根據結果的數量返回一個對象或一個對象數組。請求是通用的,因為我試圖圍繞特定的 REST API 構建一個包裝器,它被稱為:// Function prototype where I am trying to convert the responsefunc (client *Client) Get(endpoint string, data map[string]string) (map[string]json.RawMessage, error)// The way the function is calledclient.Get("/v1/users", map[string]string{"filter.abc": "lorem ipsum"})兩個響應示例:[  {    "abc": "def",    "efg": 123    "hij": [      {        "klm": "nop"      }    ]  },  {    "abc": "def",    "efg": 123    "hij": [      {        "klm": "nop"      }    ]  }]// RESPONSE 1: Array of JSON objects that have child arrays{  "abc": "def",  "efg": 123  "hij": [    {      "klm": "nop"    }  ]}// RESPONSE 2: In this case, only one element was returned.我已經實現了僅針對響應 2 執行此操作,如下所示:// [...]byteBody = ioutil.ReadAll(res.Body)// [...]var body map[string]json.RawMessageif err := json.Unmarshal(byteBody, &body); err != nil { [...] }那么,最慣用的解析方式是什么?有沒有辦法避免編寫冗余代碼并解析兩個響應?我正在考慮將響應放入的“模型”作為附加參數。這是一個好習慣嗎?非常感謝您!
查看完整描述

2 回答

?
湖上湖

TA貢獻2003條經驗 獲得超2個贊

檢查 JSON 文檔中的第一個非空白字節以確定文檔是數組還是對象。


func decodeArrayOrObject(doc []byte) ([]map[string]json.RawMessage, error) {

    trimmedDoc := bytes.TrimSpace(doc)

    switch {

    case len(trimmedDoc) == 0:

        return nil, errors.New("empty body")

    case trimmedDoc[0] == '{':

        var m map[string]json.RawMessage

        err := json.Unmarshal(doc, &m)

        return []map[string]json.RawMessage{m}, err

    case trimmedDoc[0] == '[':

        var s []map[string]json.RawMessage

        err := json.Unmarshal(doc, &s)

        return s, err

    default:

        return nil, errors.New("unexpected type")

    }

}

使用reflect包創建一個適用于任意切片類型的函數:


func decodeArrayOrObject(doc []byte, slicep interface{}) error {

    trimmedDoc := bytes.TrimSpace(doc)

    switch {

    case len(trimmedDoc) == 0:

        return errors.New("empty document")

    case trimmedDoc[0] == '[':

        return json.Unmarshal(doc, slicep)

    case trimmedDoc[0] == '{':

        s := reflect.ValueOf(slicep).Elem()

        s.Set(reflect.MakeSlice(s.Type(), 1, 1))

        return json.Unmarshal(doc, s.Index(0).Addr().Interface())

    default:

        return errors.New("unexpected type")

    }

}

使用指向結構切片的指針或指向結構指針切片的指針調用函數。


var v []Example

err := decodeArrayOrObject(body, &v)


查看完整回答
反對 回復 2022-12-19
?
呼喚遠方

TA貢獻1856條經驗 獲得超11個贊

不確定是慣用的,但這段代碼可以作為一個例子。


簡而言之,您可以嘗試以一種格式解組,如果失敗,則以另一種格式解組


關鍵功能是


func parseStr(data string) ([]Item, error) {

    item := Item{}

    if err := json.Unmarshal([]byte(data), &item); err == nil {

        return []Item{item}, nil

    }


    items := []Item{}

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

        return nil, errors.New("invalid JSON data")

    }

    return items, nil


}


查看完整回答
反對 回復 2022-12-19
  • 2 回答
  • 0 關注
  • 155 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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