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

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問題,去搜搜看,總會(huì)有你想問的

如何在 JSON 中自定義封送映射鍵

如何在 JSON 中自定義封送映射鍵

Go
胡說叔叔 2023-03-29 16:11:41
我無法理解 custom marshal intto的奇怪行為string。這是一個(gè)例子:package mainimport (    "encoding/json"    "fmt")type Int intfunc (a Int) MarshalJSON() ([]byte, error) {    test := a / 10    return json.Marshal(fmt.Sprintf("%d-%d", a, test))}func main() {    array := []Int{100, 200}    arrayJson, _ := json.Marshal(array)    fmt.Println("array", string(arrayJson))    maps := map[Int]bool{        100: true,        200: true,    }    mapsJson, _ := json.Marshal(maps)    fmt.Println("map wtf?", string(mapsJson))    fmt.Println("map must be:", `{"100-10":true, "200-20":true}`)}輸出是:array ["100-10","200-20"]map wtf? {"100":true,"200":true}map must be: {"100-10":true, "200-20":true}https://play.golang.org/p/iiUyL2Hc5h_P我錯(cuò)過了什么?
查看完整描述

2 回答

?
絕地?zé)o雙

TA貢獻(xiàn)1946條經(jīng)驗(yàn) 獲得超4個(gè)贊

這是預(yù)期的結(jié)果,記錄在json.Marshal():


映射值編碼為 JSON 對(duì)象。映射的鍵類型必須是字符串、整數(shù)類型或?qū)崿F(xiàn) encoding.TextMarshaler。通過應(yīng)用以下規(guī)則對(duì)映射鍵進(jìn)行排序并將其用作 JSON 對(duì)象鍵,并遵守針對(duì)上述字符串值描述的 UTF-8 強(qiáng)制轉(zhuǎn)換:


- string keys are used directly

- encoding.TextMarshalers are marshaled

- integer keys are converted to strings

請(qǐng)注意,映射鍵的處理方式與屬性值的處理方式不同,因?yàn)?JSON 中的映射鍵是始終為值的屬性名稱string(而屬性值可能是 JSON 文本、數(shù)字和布爾值)。


根據(jù)文檔,如果您希望它也適用于地圖鍵,請(qǐng)實(shí)施encoding.TextMarshaler:


func (a Int) MarshalText() (text []byte, err error) {

    test := a / 10

    return []byte(fmt.Sprintf("%d-%d", a, test)), nil

}

(請(qǐng)注意,它MarshalText()應(yīng)該返回“只是”簡單文本,而不是 JSON 文本,因此我們?cè)谄渲惺÷粤?JSON 封送處理?。?/p>


這樣,輸出將是(在Go Playground上嘗試):


array ["100-10","200-20"] <nil>

map wtf? {"100-10":true,"200-20":true} <nil>

map must be: {"100-10":true, "200-20":true}

請(qǐng)注意,這就encoding.TextMarshaler足夠了,因?yàn)樵诰幗M為值時(shí)也會(huì)檢查它,而不僅僅是映射鍵。所以你不必同時(shí)實(shí)現(xiàn)encoding.TextMarshaler和json.Marshaler。


如果你同時(shí)實(shí)現(xiàn)了這兩者,當(dāng)值被編組為“簡單”值和映射鍵時(shí),你可以有不同的輸出,因?yàn)閖son.Marshaler在生成值時(shí)優(yōu)先:


func (a Int) MarshalJSON() ([]byte, error) {

    test := a / 100

    return json.Marshal(fmt.Sprintf("%d-%d", a, test))

}


func (a Int) MarshalText() (text []byte, err error) {

    test := a / 10

    return []byte(fmt.Sprintf("%d-%d", a, test)), nil

}

這次輸出將是(在Go Playground上試試):


array ["100-1","200-2"] <nil>

map wtf? {"100-10":true,"200-20":true} <nil>

map must be: {"100-10":true, "200-20":true}


查看完整回答
反對(duì) 回復(fù) 2023-03-29
?
侃侃爾雅

TA貢獻(xiàn)1801條經(jīng)驗(yàn) 獲得超16個(gè)贊

接受的答案很好,但我不得不重新搜索足夠多的時(shí)間,所以我想通過示例給出關(guān)于編組/解組的完整答案,所以下次我可以只復(fù)制粘貼作為起點(diǎn):)

我經(jīng)常搜索的內(nèi)容包括:

  • 將自定義類型編碼到 sql 數(shù)據(jù)庫

  • json 將 enum int 編碼為字符串

  • json編碼映射鍵但不編碼值

在這個(gè)例子中,我創(chuàng)建了一個(gè)自定義的 Weekday 類型,它匹配 time.Weekday int 值,但允許請(qǐng)求/響應(yīng) json 和數(shù)據(jù)庫中的字符串值

同樣的事情可以用任何使用 iota 的 int 枚舉來完成,以便在 json 和數(shù)據(jù)庫中具有人類可讀的值

游樂場測試示例https://go.dev/play/p/aUxxIJ6tY9K

重要的一點(diǎn)在這里:

var (

    // read/write from/to json values

    _ json.Marshaler   = (*Weekday)(nil)

    _ json.Unmarshaler = (*Weekday)(nil)


    // read/write from/to json keys

    _ encoding.TextMarshaler   = (*Weekday)(nil)

    _ encoding.TextUnmarshaler = (*Weekday)(nil)


    // read/write from/to sql

    _ sql.Scanner   = (*Weekday)(nil)

    _ driver.Valuer = (*Weekday)(nil)

)


// MarshalJSON marshals the enum as a quoted json string

func (w Weekday) MarshalJSON() ([]byte, error) {

    return []byte(`"` + w.String() + `"`), nil

}


func (w Weekday) MarshalText() (text []byte, err error) {

    return []byte(w.String()), nil

}


func (w *Weekday) UnmarshalJSON(b []byte) error {

    return w.UnmarshalText(b)

}


func (w *Weekday) UnmarshalText(b []byte) error {

    var dayName string

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

        return err

    }


    d, err := ParseWeekday(dayName)

    if err != nil {

        return err

    }


    *w = d

    return nil

}


// Value is used for sql exec to persist this type as a string

func (w Weekday) Value() (driver.Value, error) {

    return w.String(), nil

}


// Scan implements sql.Scanner so that Scan will be scanned correctly from storage

func (w *Weekday) Scan(src interface{}) error {

    switch t := src.(type) {

    case int:

        *w = Weekday(t)

    case int64:

        *w = Weekday(int(t))

    case string:

        d, err := ParseWeekday(t)

        if err != nil {

            return err

        }

        *w = d

    case []byte:

        d, err := ParseWeekday(string(t))

        if err != nil {

            return err

        }

        *w = d

    default:

        return errors.New("Weekday.Scan requires a string or byte array")

    }

    return nil

}


請(qǐng)注意,var 塊只是強(qiáng)制您正確地實(shí)現(xiàn)這些方法,否則它不會(huì)編譯。


另請(qǐng)注意,如果您排除MarshalJSON然后 go 將在它存在時(shí)使用MarshalText,因此如果您只希望鍵具有自定義編組但具有值的默認(rèn)行為那么您不應(yīng)該在您的主要類型上使用這些方法,而是具有僅用于映射鍵的包裝器類型


type MyType struct{}

type MyTypeKey MyType

var (

    // read/write from/to json keys

    _ encoding.TextMarshaler   = (*MyTypeKey)(nil)

    _ encoding.TextUnmarshaler = (*MyTypeKey)(nil)

)

func (w MyTypeKey) MarshalText() (text []byte, err error) {

    return []byte(w.String()), nil

}


func (w *MyTypeKey) UnmarshalText(b []byte) error {

    *w = MyTypeKey(ParseMyType(string(b)))

    return nil

}

隨意改進(jìn)這個(gè)答案,我希望其他人發(fā)現(xiàn)它有幫助,我希望下次我能再次找到它并自己再次搜索它:)


查看完整回答
反對(duì) 回復(fù) 2023-03-29
  • 2 回答
  • 0 關(guān)注
  • 108 瀏覽

添加回答

舉報(bào)

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

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