什么输入会导致golang的json.Marshal返回错误?

mdw*_*ott 30 json marshalling go

来自文档:

JSON不能表示循环数据结构,Marshal不能处理它们.将循环结构传递给Marshal将导致无限递归.

我遇到过这种情况,导致运行时恐慌.

我想知道的是,是否有人可以提供一个工作程序来演示非恐慌情况,其中json.Marshal返回非零错误.最佳答案显然包括使用的输入.

hbe*_*gel 26

只是为了补充Jonathan的答案,json.Marshal函数可以返回两种类型的错误:UnsupportedTypeErrorUnsupportedValueError

第一个可能是由于乔纳森试图将一个无效类型称为元素:

_, err := json.Marshal(make(chan int))
_, ok := err.(*json.UnsupportedTypeError) // ok == true
Run Code Online (Sandbox Code Playgroud)

另一方面,您还可以让Marshal函数通过传递无效值来返回错误:

_, err := json.Marshal(math.Inf(1))
_, ok := err.(*json.UnsupportedValueError) // ok == true
Run Code Online (Sandbox Code Playgroud)

  • 那么这是否可以解释为“只要类型不改变”,就可以安全地忽略“err”? (7认同)

Jon*_*ver 20

更新:现在使用通道而不是map [int] int来引出错误


特定于Go的结构,例如funcchan拒绝序列化:

package main

import (
    "encoding/json"
    "fmt"
)

func main() {
    value := make(chan int)
    _, err := json.Marshal(value)
    fmt.Println(err)
}
Run Code Online (Sandbox Code Playgroud)


Ano*_*usX 5

阅读源代码可以找到这样一个判断编码器的函数,如果不存在会返回编组错误: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
    }
}
Run Code Online (Sandbox Code Playgroud)

我们可以在https://github.com/golang/go/blob/master/src/reflect/type.go找到各种枚举

所以不难看出,不在上述函数中的种类是无法编组的:

UnsafePointer,Complex64,Complex128,Chan,Func
Run Code Online (Sandbox Code Playgroud)

例子:

UnsafePointer,Complex64,Complex128,Chan,Func
Run Code Online (Sandbox Code Playgroud)