Golang encoding/json
包允许您使用,string
struct标记,以便将字符串值(例如"309230"
)编组/解组到int64
字段中。例如:
Int64String int64 `json:",string"`
然而,这对切片不起作用,即。 []int64
:
Int64Slice []int64 `json:",string"` // Doesn't work.
有没有办法将JSON字符串数组编组/解组到[] int64字段中?
引自https://golang.org/pkg/encoding/json:
“string”选项表示字段在JSON编码的字符串中存储为JSON。它仅适用于字符串,浮点,整数或布尔类型的字段。在与JavaScript程序通信时,有时会使用这种额外的编码级别:
答案 0 :(得分:4)
对于任何有兴趣的人,我找到了使用定义了MarshalJSON()
和UnmarshalJSON()
方法的自定义类型的解决方案。
type Int64StringSlice []int64
func (slice Int64StringSlice) MarshalJSON() ([]byte, error) {
values := make([]string, len(slice))
for i, value := range []int64(slice) {
values[i] = fmt.Sprintf(`"%v"`, value)
}
return []byte(fmt.Sprintf("[%v]", strings.Join(values, ","))), nil
}
func (slice *Int64StringSlice) UnmarshalJSON(b []byte) error {
// Try array of strings first.
var values []string
err := json.Unmarshal(b, &values)
if err != nil {
// Fall back to array of integers:
var values []int64
if err := json.Unmarshal(b, &values); err != nil {
return err
}
*slice = values
return nil
}
*slice = make([]int64, len(values))
for i, value := range values {
value, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return err
}
(*slice)[i] = value
}
return nil
}
上述解决方案将[]int64
封送到JSON字符串数组中。 Unmarshaling适用于JSON字符串和整数数组,即:
{"bars": ["1729382256910270462", "309286902808622", "23"]}
{"bars": [1729382256910270462, 309286902808622, 23]}
上的示例
答案 1 :(得分:2)
正如您从json.Marshal()
引用的那样,,string
选项仅适用于特定类型,即:
"字符串"选项表示字段在JSON编码的字符串中存储为JSON。 它仅适用于字符串,浮点,整数或布尔类型的字段。
您希望它与切片一起使用,但json
包不支持。
如果您仍然需要此功能,则必须编写自定义编组/解组逻辑。
你所呈现的作品,但它不必要地复杂。这是因为您在切片上创建了自定义逻辑,但您只希望在切片(数组)的各个元素上使用此功能。您不想改变渲染或解析数组/切片(作为元素序列)的方式。
因此,更简单的解决方案是仅创建自定义"数字"生成此行为的类型,此自定义类型的切片元素的行为将相同。
我们的自定义数字类型和编组/解组逻辑:
type Int64Str int64
func (i Int64Str) MarshalJSON() ([]byte, error) {
return json.Marshal(strconv.FormatInt(int64(i), 10))
}
func (i *Int64Str) UnmarshalJSON(b []byte) error {
// Try string first
var s string
if err := json.Unmarshal(b, &s); err == nil {
value, err := strconv.ParseInt(s, 10, 64)
if err != nil {
return err
}
*i = Int64Str(value)
return nil
}
// Fallback to number
return json.Unmarshal(b, (*int64)(i))
}
这就是全部!
使用它的类型:
type Foo struct {
Bars []Int64Str `json:"bars"`
}
以与您相同的方式测试它会产生相同的结果。在Go Playground上尝试。