Golang:JSON:如何将字符串数组解组为[] int64

时间:2018-03-21 20:02:56

标签: json go

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程序通信时,有时会使用这种额外的编码级别:

2 个答案:

答案 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]}

请参阅https://play.golang.org/p/BOqUBGR3DXm

上的示例

答案 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上尝试。