gpt4 book ai didi

json - 如何在 JSON 中自定义编码(marshal)映射键

转载 作者:IT王子 更新时间:2023-10-29 01:23:02 33 4
gpt4 key购买 nike

我无法理解自定义编码 intstring 的奇怪行为。

这是一个例子:

package main

import (
"encoding/json"
"fmt"
)

type Int int

func (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

我错过了什么?

最佳答案

这是预期的结果,记录在 json.Marshal() 中:

Map values encode as JSON objects. The map's key type must either be a string, an integer type, or implement encoding.TextMarshaler. The map keys are sorted and used as JSON object keys by applying the following rules, subject to the UTF-8 coercion described for string values above:

- string keys are used directly
- encoding.TextMarshalers are marshaled
- integer keys are converted to strings

请注意,映射键与属性值的处理方式不同,因为 JSON 中的映射键是始终为 string 值的属性名称(而属性值可能是 JSON 文本、数字和 bool 值)。

根据文档,如果您希望它也适用于 map 键,请实现 encoding.TextMarshaler :

func (a Int) MarshalText() (text []byte, err error) {
test := a / 10
return []byte(fmt.Sprintf("%d-%d", a, test)), nil
}

(请注意,MarshalText() 应该返回“仅”简单文本,而不是 JSON 文本,因此我们在其中省略了 JSON 编码(marshal)处理!)

这样,输出将是(在 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}

请注意 encoding.TextMarshaler 就足够了,因为在将其编码为值时也会检查它,而不仅仅是映射键。所以你不必同时实现 encoding.TextMarshalerjson.Marshaler .

如果你同时实现了这两者,当值被编码为“简单”值和映射键时,你可以有不同的输出,因为 json.Marshaler 在生成值时优先:

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}

关于json - 如何在 JSON 中自定义编码(marshal)映射键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52161555/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com