-
芜湖不芜
只是为了补充乔纳森的回答, json.Marshal 函数可以返回两种类型的错误:UnsupportedTypeError或UnsupportedValueError第一个可能是由 Jonathan 所说的,通过尝试对无效类型进行编组:_, err := json.Marshal(make(chan int))_, ok := err.(*json.UnsupportedTypeError) // ok == true另一方面,您还可以通过传递无效值让 Marshal 函数返回错误:_, err := json.Marshal(math.Inf(1))_, ok := err.(*json.UnsupportedValueError) // ok == true
-
尚方宝剑之说
更新:现在使用通道而不是 map[int]int 来引发错误特定于 Go 的结构,例如func或chan拒绝序列化:package mainimport ( "encoding/json" "fmt")func main() { value := make(chan int) _, err := json.Marshal(value) fmt.Println(err)}
-
慕码人8056858
阅读源代码可以找到这样一个判断编码器的函数,如果不存在会返回编组错误:https : //github.com/golang/go/blob/master/src/encoding/json/encode.gofunc newTypeEncoder(t reflect.Type, allowAddr bool) encoderFunc { // ignored switch t.Kind() { case reflect.Bool: return boolEncoder case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return intEncoder case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return uintEncoder case reflect.Float32: return float32Encoder case reflect.Float64: return float64Encoder case reflect.String: return stringEncoder case reflect.Interface: return interfaceEncoder case reflect.Struct: return newStructEncoder(t) case reflect.Map: return newMapEncoder(t) case reflect.Slice: return newSliceEncoder(t) case reflect.Array: return newArrayEncoder(t) case reflect.Ptr: return newPtrEncoder(t) default: return unsupportedTypeEncoder }}我们可以在https://github.com/golang/go/blob/master/src/reflect/type.go找到各种枚举所以不难看出,不在上述函数中的种类是无法编组的:UnsafePointer,Complex64,Complex128,Chan,Func例子: json.Marshal(unsafe.Pointer(nil)) // UnsafePointer json.Marshal(complex64(1)) // Complex64 json.Marshal(complex128(1)) // Complex128 json.Marshal(make(chan struct{})) // Chan json.Marshal(func() {}) // Func
-
临摹微笑
前段时间我正在解决一个在golang中序列化/反序列化循环引用的问题,所有链接都指向这个问题。然而,这有点误导,因为问题更广泛。如果你遇到了和我一样的情况,并且找不到如何处理循环引用的解决方案,你现在可以使用tahwil——我在 github 上发布的一个新库。据我所知,它现在是唯一一个以通用方式促进循环数据结构的序列化/反序列化的库。自述文件提供了有关如何使用该库的信息,因此我将在此处仅复制示例。编码:package mainimport ( "encoding/json" "fmt" "github.com/go-extras/tahwil")type Person struct { Name string Parent *Person Children []*Person}func main() { parent := &Person{ Name: "Arthur", Children: []*Person{ { Name: "Ford", }, { Name: "Trillian", }, }, } parent.Children[0].Parent = parent parent.Children[1].Parent = parent v, err := tahwil.ToValue(parent) if err != nil { panic(err) } res, err := json.Marshal(v) if err != nil { panic(err) } fmt.Println(string(res))}解码:package mainimport ( "encoding/json" "fmt" "github.com/go-extras/tahwil")type Person struct { Name string `json:"name"` Parent *Person `json:"parent"` Children []*Person `json:"children"`}func prepareData() []byte { parent := &Person{ Name: "Arthur", Children: []*Person{ { Name: "Ford", }, { Name: "Trillian", }, }, } parent.Children[0].Parent = parent parent.Children[1].Parent = parent v, err := tahwil.ToValue(parent) if err != nil { panic(err) } res, err := json.Marshal(v) if err != nil { panic(err) } return res}func main() { data := &tahwil.Value{} res := prepareData() err := json.Unmarshal(res, data) if err != nil { panic(err) } person := &Person{} err = tahwil.FromValue(data, person) if err != nil { panic(err) } fmt.Printf(`Name: %sChildren: - %s -- parent name: %s - %s -- parent name: %s`, person.Name, person.Children[0].Name, person.Children[0].Parent.Name, person.Children[1].Name, person.Children[1].Parent.Name)}主要思想是将原始数据转换为tahwil.Value{},这实际上将refid'添加到您的所有字段中。每当tahwil遇到循环引用时,它都会用引用替换实际对象。之后,该图在技术上不再是循环的,因此可以编组为 json。恢复数据意味着反向操作,即任何引用都将被指向对象的指针替换。PS 为什么tahwil?我试图为这个名字找到一些不常见的词,并找到了一个阿拉伯语词(تحويل),意思是转换。