外部类型问题的 JSON 序列化 - 将 map[string]interface{} 项转换为 int

标签 json go marshalling

我想序列化类型Dense包装 gonum.org/v1/gonum/mat .因为我无法实现外部类型的方法,所以我创建了一个类型

type DenseEx struct {
    Mtx *mat.Dense
}

并实现MarshalJSON方法如下
func (d DenseEx) MarshalJSON() ([]byte, error) {
    js := map[string]interface{}{}
    rows, cols := d.Mtx.Dims()
    js["cols"] = cols
    js["rows"] = rows
    fltVals := make([]float64, cols*rows)
    for r := 0; r < rows; r++ {
       for c := 0; c < cols; c++ {
            i := r*cols + c
            fltVals[i] = d.Mtx.At(r, c)
        }
    }
  js["values"] = fltVals
  return json.Marshal(js)
}

这按预期工作。现在我有解码结构的问题。
func (d DenseEx) UnmarshalJSON(data []byte) error {
    js := map[string]interface{}{}
    err := json.Unmarshal(data, &js)
    if err != nil {
        return err
    }
    intf, ok := js["cols"]
    if !ok {
        return fmt.Errorf("tag 'cols' missing in JSON data")
    }
    var cols, rows int
    cols, ok = intf.(int)
    if !ok {
        return fmt.Errorf("tag 'cols' cannot be converted to int")
    }
    ...
    return nil
}

我无法将标签的值转换为正确的类型。我的测试 json 字符串是
var jsonStrs = []struct {
    str         string
    expected    DenseEx
    description string
}{
    {
        str: "{\"cols\":3,\"rows\":2,\"values\":[6,1,5,2,4,3]}",
        expected: DenseEx{
            Mtx: nil,
        },
        description: "deserialization of a 2x3 matrice",
    },
}

我的测试代码是
...
for _, d := range jsonStrs {
    var m DenseEx
    err := m.UnmarshalJSON([]byte(d.str))
...

我总是得到结果
matex_test.go:26: FAIL: deserialization of a 2x3 matrice: tag 'cols' cannot be converted to int

有任何想法吗?

提前致谢!

最佳答案

如果您查看 docs编码(marshal)的。你会发现 Unmarshal 中 Numbers 的已知类型是 float64
为了将 JSON 解码为接口(interface)值,Unmarshal 将其中一项存储在接口(interface)值中:

bool, for JSON booleans
float64, for JSON numbers
string, for JSON strings
[]interface{}, for JSON arrays
map[string]interface{}, for JSON objects
nil for JSON null

因此,当您尝试 Unmarshal an int 时,您将得到它作为 float 64。应该首先将其键入断言 float64 intf.(float64)然后将其转换为 int
例如 :
    intf, ok := js["cols"]
    if !ok {
        return fmt.Errorf("tag 'cols' missing in JSON data")
    }
    var cols, rows int

    ucols, ok := intf.(float64)
    if !ok {
        return fmt.Errorf("tag 'cols' cannot be converted to float64")
    } 

    cols = int(ucols)

关于外部类型问题的 JSON 序列化 - 将 map[string]interface{} 项转换为 int,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60965125/

相关文章:

go - 这是实现超时的常见方法,为什么 time.After 不起作用

c# - 如何使用 Marshal.SizeOf 忽略结构中的字段大小?

c# - GCHandle。如何固定包含定义为类的字段的对象

jquery - 解析多级JSON

json - ngFor 对于复杂的 json

image - Golang 使 RGBA 图像显示奇怪的颜色

python - Go 与 Python 的 crypt.crypt 等价的是什么?

c++ - Marshal 管理了无符号整数的非托管数组

java - 在 Gson 中,如何将 JsonArray 添加到 JsonObject?

java - 如何将两个 Json 列表从 Java Servlet 传递到 HTML 页面?