4 回答

TA貢獻(xiàn)1796條經(jīng)驗(yàn) 獲得超7個(gè)贊
只是為了補(bǔ)充喬納森的回答, json.Marshal 函數(shù)可以返回兩種類(lèi)型的錯(cuò)誤:UnsupportedTypeError或UnsupportedValueError
第一個(gè)可能是由 Jonathan 所說(shuō)的,通過(guò)嘗試對(duì)無(wú)效類(lèi)型進(jìn)行編組:
_, err := json.Marshal(make(chan int))
_, ok := err.(*json.UnsupportedTypeError) // ok == true
另一方面,您還可以通過(guò)傳遞無(wú)效值讓 Marshal 函數(shù)返回錯(cuò)誤:
_, err := json.Marshal(math.Inf(1))
_, ok := err.(*json.UnsupportedValueError) // ok == true

TA貢獻(xiàn)1788條經(jīng)驗(yàn) 獲得超4個(gè)贊
更新:現(xiàn)在使用通道而不是 map[int]int 來(lái)引發(fā)錯(cuò)誤
特定于 Go 的結(jié)構(gòu),例如func或chan拒絕序列化:
package main
import (
"encoding/json"
"fmt"
)
func main() {
value := make(chan int)
_, err := json.Marshal(value)
fmt.Println(err)
}

TA貢獻(xiàn)1803條經(jīng)驗(yàn) 獲得超6個(gè)贊
閱讀源代碼可以找到這樣一個(gè)判斷編碼器的函數(shù),如果不存在會(huì)返回編組錯(cuò)誤:https : //github.com/golang/go/blob/master/src/encoding/json/encode.go
func 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找到各種枚舉
所以不難看出,不在上述函數(shù)中的種類(lèi)是無(wú)法編組的:
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

TA貢獻(xiàn)1982條經(jīng)驗(yàn) 獲得超2個(gè)贊
前段時(shí)間我正在解決一個(gè)在golang中序列化/反序列化循環(huán)引用的問(wèn)題,所有鏈接都指向這個(gè)問(wèn)題。然而,這有點(diǎn)誤導(dǎo),因?yàn)閱?wèn)題更廣泛。
如果你遇到了和我一樣的情況,并且找不到如何處理循環(huán)引用的解決方案,你現(xiàn)在可以使用tahwil——我在 github 上發(fā)布的一個(gè)新庫(kù)。據(jù)我所知,它現(xiàn)在是唯一一個(gè)以通用方式促進(jìn)循環(huán)數(shù)據(jù)結(jié)構(gòu)的序列化/反序列化的庫(kù)。
自述文件提供了有關(guān)如何使用該庫(kù)的信息,因此我將在此處僅復(fù)制示例。
編碼:
package main
import (
"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 main
import (
"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: %s
Children:
- %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)
}
主要思想是將原始數(shù)據(jù)轉(zhuǎn)換為tahwil.Value{},這實(shí)際上將refid'添加到您的所有字段中。每當(dāng)tahwil遇到循環(huán)引用時(shí),它都會(huì)用引用替換實(shí)際對(duì)象。之后,該圖在技術(shù)上不再是循環(huán)的,因此可以編組為 json。
恢復(fù)數(shù)據(jù)意味著反向操作,即任何引用都將被指向?qū)ο蟮闹羔樚鎿Q。
PS 為什么tahwil?我試圖為這個(gè)名字找到一些不常見(jiàn)的詞,并找到了一個(gè)阿拉伯語(yǔ)詞(?????),意思是轉(zhuǎn)換。
- 4 回答
- 0 關(guān)注
- 209 瀏覽
添加回答
舉報(bào)