外部类型问题的JSON序列化-将映射[string]接口{}项转换为int
我想序列化包gonum.org/v1/gonum/mat的类型。因为我无法实现外部类型的方法,所以我创建了一个类型外部类型问题的JSON序列化-将映射[string]接口{}项转换为int,json,go,marshalling,Json,Go,Marshalling,我想序列化包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["co
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)
}
我无法将标记的值转换为正确的类型。我的测试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
有什么想法吗
提前谢谢 如果您检查解组的。您将发现解组中已知的数字类型是float64
要将JSON解组为接口值,解组将在接口值中存储以下内容之一:
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
因此,当您尝试解组一个int时,您将得到它作为float 64。应该首先将其键入assert到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)
请尝试intf.float64,enconding/json将json数字解组到的默认类型。如本文所述,map[string]接口{}{}可能看起来很方便,但请定义一个以行、列和值为字段的类型,它要简单得多。@mkopriva:谢谢您对文档的提示。它修复了它@沃尔克:这是我想避免的。因为接下来我必须定义类似的东西:类型T struct{rows int cols int values[]float},然后我将在稠密和T结构中保留冗余数据。之后,我只对致密结构进行了研究,你们不明白我的意思。您的类型DenseEx struct{Mtx mat.Dense}非常好,我从未建议对其进行丝毫更改。使用它,并像您所做的那样附加UnmarshalJSON和MarshalJSON。我的建议是,在这两个方法中,您不应该使用map[string]interface{},而应该使用类似smth的类型T struct{Rows,Cols int;Values[]float64}。在MarshalJSON中,您可以从d.Mtx.Dims和d.Mtx.At完全像您一样填充这样的T。然后用普通编码/json.Marshal序列化这个T。在UnmarshalJSON中,您可以用另一种方式进行。这确实有效,不会导致您认为它会导致的问题。真正地试试看。当然你不能把垫子放在这样一个T形的内部,但我从来没有建议过这样做。
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)