dshdsh2016 2018-03-12 15:50
浏览 70
已采纳

可以将map [string] string编组到json是否可以返回错误?

Say I have the following code:

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

Is there any way in this case that the json.Marshal call would return an error?

I'm wondering partly out of curiosity and partly to consider whether I need to worry about that error check at all.

  • 写回答

1条回答 默认 最新

  • dongpi2503 2018-03-12 16:32
    关注

    Since any valid string value is a valid key and also a valid value in JSON (for details see Which characters are valid/invalid in a JSON key name?), theoretically it won't return any errors.

    If an out of memory error would occur, json.Marshal() would not return, your app would terminate with an error code.

    Since Go stores string values as their UTF-8 encoded byte sequences, there is the question of invalid UTF-8 encoded string content. This also won't result in any errors, as Go will substitute invalid code points with the Unicode replacement character U+FFFD, like in this example:

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

    Output (try it on the Go Playground):

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

    This behavior is documented at json.Marshal():

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

    It may be that marshaling a map[string]string will never return an error, still, you should always check returned errors unless the doc explicitly states that the returned error is always nil (the doc of json.Marshal() does not document such behavior). Such rare example is rand.Read() which documents that "it always returns len(p) and a nil error".

    And there is also the possibility that the standard library has errors, so even though the implementation of the json package may not intend to return any error when marshaling a map[string]string, a bug may cause it to still return a non-nil error.

    Also see related question: Go : When will json.Unmarshal to struct return error?

    Concurrent map modification

    For completeness, let's discuss another issue that might cause json.Marshal() to fail when a map[string]string is passed to it.

    Go 1.6 added a lightweight concurrent misuse of maps detection to the runtime, you can read more about it here: How to recover from concurrent map writes?

    This means that the Go runtime may detect if a map is read or modified in a goroutine, and it is also modified by another goroutine, concurrently, without synchronization.

    So the scenario here is that we pass a map[string]string to json.Marshal(). And for it to be marshaled, the json package has to iterate over the key-values of the map obviously. If we modify the map concurrently, that will result in a fail.

    Here is a sample code that provokes it (the loop is there to increase the likeliness of the concurrent modification, else we would be in the hands of the goroutine scheduler):

    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)
        }
    }
    

    Also note that in this case json.Marshal() will also not return (just like with the case of the out-of-memory error), instead the runtime will crash your app, intentionally. Output will be:

    fatal error: concurrent map iteration and map write
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 access多表提取相同字段数据并合并
  • ¥20 基于MSP430f5529的MPU6050驱动,求出欧拉角
  • ¥20 Java-Oj-桌布的计算
  • ¥15 powerbuilder中的datawindow数据整合到新的DataWindow
  • ¥20 有人知道这种图怎么画吗?
  • ¥15 pyqt6如何引用qrc文件加载里面的的资源
  • ¥15 安卓JNI项目使用lua上的问题
  • ¥20 RL+GNN解决人员排班问题时梯度消失
  • ¥60 要数控稳压电源测试数据
  • ¥15 能帮我写下这个编程吗