我想序列化类型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/