json - 可以将 map[string]string 编码为 json 返回错误吗?

标签 json dictionary go marshalling

假设我有以下代码:

m := map[string]string{}
//... do stuff to the map
b, err := json.Marshal(m)

在这种情况下,json.Marshal 调用会返回错误吗?

我想知道,部分是出于好奇,部分是为了考虑我是否需要担心错误检查。

最佳答案

由于任何有效的 string 值都是有效的键,也是 JSON 中的有效值(详情请参阅 Which characters are valid/invalid in a JSON key name? ),理论上它不会返回任何错误。

如果发生内存不足错误,json.Marshal()不会返回,您的应用程序将终止并显示错误代码。

由于 Go 将 string 值存储为其 UTF-8 编码字节序列,因此存在无效 UTF-8 编码字符串内容的问题。这也不会导致任何错误,因为 Go 将用 Unicode 替换字符 U+FFFD 替换无效代码点,如本例所示:

m := map[string]string{"\xff": "a"}
data, err := json.Marshal(m)
fmt.Println(string(data), err)

输出(在 Go Playground 上尝试):

{"\ufffd":"a"} <nil>

此行为记录在 json.Marshal() 中:

String values encode as JSON strings coerced to valid UTF-8, replacing invalid bytes with the Unicode replacement rune.

编码(marshal) map[string]string 可能永远不会返回错误,不过,您应该始终检查返回的错误,除非文档明确指出返回的 error 始终为 nil(json.Marshal() 的文档未记录此类行为)。这种罕见的例子是 rand.Read()其中记录“它总是返回 len(p) 和一个 nil 错误”

而且标准库也有可能有错误,所以即使 json 包的实现可能不会打算在编码 map[string]string,一个错误可能会导致它仍然返回一个非nil错误。

另见相关问题:Go : When will json.Unmarshal to struct return error?

并发 map 修改

为了完整起见,让我们讨论另一个可能导致 json.Marshal() 在传递 map[string]string 时失败的问题。

Go 1.6 added轻量级并发误用映射检测到运行时,您可以在此处阅读更多相关信息:How to recover from concurrent map writes?

这意味着 Go 运行时可以检测一个映射是否在一个 goroutine 中被读取或修改,并且它也被另一个 goroutine 同时修改,没有同步。

所以这里的场景是我们传递一个map[string]stringjson.Marshal()。为了对其进行编码,json 包显然必须遍历 map 的键值。如果我们同时修改 map ,将导致失败。

这是一个激发它的示例代码(循环是为了增加并发修改的可能性,否则我们将落入 goroutine 调度程序的手中):

m := map[string]string{"\xff": "a"}

go func() {
    for i := 0; i < 10000; i++ {
        m["x"] = "b"
    }
}()

for i := 0; i < 10000; i++ {
    if _, err := json.Marshal(m); err != nil {
        panic(err)
    }
}

另请注意,在这种情况下 json.Marshal() 也不会返回(就像内存不足错误的情况一样),相反,运行时会故意使您的应用程序崩溃.输出将是:

fatal error: concurrent map iteration and map write

关于json - 可以将 map[string]string 编码为 json 返回错误吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49239367/

相关文章:

json - 使用 Observable 在 Angular 2 中发出轮询请求

python - 使用 python 重复条目求和到 K

python - 用 csv.DictWriter 写入部分行?

go - 确保 goroutine 清理,最佳实践

go - 将一个元素添加到 nil slice 将容量增加 2

javascript - 具有多个 key 对的 JSON 的适当数据结构

json - 如何计算 Postgres JSON 数组中的整体百分比?

javascript - 如何访问另一个数组中的对象数组中的 ID 或名称?

Python 在 JSON 字典中搜索特定值并返回该键

mysql - 我应该在 Go Web 应用程序中始终打开 1 个全局数据库连接吗?或者我应该每次都打开并关闭它?