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

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

如何為從 Go 中的標量派生的類型實現 UnmarshalJSON?

如何為從 Go 中的標量派生的類型實現 UnmarshalJSON?

Go
aluckdog 2021-12-06 19:13:19
我有一個簡單的類型,它在 Go 中實現了子類型整數常量到字符串的轉換,反之亦然。我希望能夠將 JSON 中的字符串自動解組為這種類型的值。我不能,因為 UnmarshalJSON 沒有給我返回或修改標量值的方法。它需要一個結構,其成員由 UnmarshalJSON 設置。",string" 方法不適用于內置標量類型以外的其他類型。有沒有辦法為派生的標量類型正確實現 UnmarshalJSON?這是我所追求的一個例子。我希望它打印“Hello Ralph”四次,但它打印“Hello Bob”四次,因為 PersonID 沒有改變。package mainimport (    "encoding/json"    "fmt")type PersonID intconst (    Bob PersonID = iota    Jane    Ralph    Nobody = -1)var nameMap = map[string]PersonID{    "Bob":    Bob,    "Jane":   Jane,    "Ralph":  Ralph,    "Nobody": Nobody,}var idMap = map[PersonID]string{    Bob:    "Bob",    Jane:   "Jane",    Ralph:  "Ralph",    Nobody: "Nobody",}func (intValue PersonID) Name() string {    return idMap[intValue]}func Lookup(name string) PersonID {    return nameMap[name]}func (intValue PersonID) UnmarshalJSON(data []byte) error {    // The following line is not correct    intValue = Lookup(string(data))    return nil}type MyType struct {    Person   PersonID `json: "person"`    Count    int      `json: "count"`    Greeting string   `json: "greeting"`}func main() {    var m MyType    if err := json.Unmarshal([]byte(`{"person": "Ralph", "count": 4, "greeting": "Hello"}`), &m); err != nil {        fmt.Println(err)    } else {        for i := 0; i < m.Count; i++ {            fmt.Println(m.Greeting, m.Person.Name())        }    }}
查看完整描述

2 回答

?
江戶川亂折騰

TA貢獻1851條經驗 獲得超5個贊

對解組方法使用指針接收器。如果使用值接收器,則在方法返回時對接收器的更改將丟失。


unmarshal 方法的參數是 JSON 文本。解組 JSON 文本以獲得刪除所有 JSON 引用的純字符串。


func (intValue *PersonID) UnmarshalJSON(data []byte) error {

  var s string

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

    return err

  }

  *intValue = Lookup(s)

  return nil

}

JSON 標記與示例 JSON 之間存在不匹配。我更改了 JSON 以匹配標簽,但您可以通過其他方式更改它。


if err := json.Unmarshal([]byte(`{"person": "Ralph", "count": 4, "greeting": "Hello"}`), &m); err != nil {

playground example


查看完整回答
反對 回復 2021-12-06
?
揚帆大魚

TA貢獻1799條經驗 獲得超9個贊

這是基于我的評論的答案。我不確定這正是您想要做的,因為您的一些問題措辭讓我感到困惑,但基本思想是將解組和轉換分成兩個不同的步驟。首先將原始數據解組為兼容類型,然后轉換為另一種類型或豐富您已經擁有的類型,如下例所示。歡迎您在自定義實現中隱藏此行為UnmarshalJSON如果你愿意,但我個人建議不要這樣做。這是我的兩個原因;1) 它只是與 Go 的顯式冗長編碼風格不一致 2) 我鄙視高度混淆的包/庫/語言,它們為你做這樣的事情,因為遲早它會咬你的屁股,比添加 1 花費更多在幾個地方有一行額外的代碼(比如幾個小時試圖調試對你來說毫無意義的東西)。


type MyType struct {

    Id   PersonID

    Name     string   `json: "name"` 

    Count    int      `json: "count"`

    Greeting string   `json: "greeting"`

}



func main() {

    var m MyType

    if err := json.Unmarshal([]byte(`{"name": "Ralph", "count": 4, "greeting": "Hello"}`), &m); err != nil {

        fmt.Println(err)

    } else {

        m.Id = Lookup(m.Name) // see this isn't unmarshalling

        // better to take the data as is and do transformation separate

        for i := 0; i < m.Count; i++ {

            fmt.Println(m.Greeting, m.Person.Name())

        }

    }

}


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

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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