You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go语言中JSON反序列化为map时如何保留键值顺序?为何map输出顺序并非完全随机?

Hey there! Let's tackle your two questions about JSON deserialization and Go map order clearly.

1. Preserving JSON Key-Value Order When Deserializing

The standard map[string]T type in Go doesn't preserve insertion or JSON-defined order, which is why your output is shuffled. To fix this, you have two solid options depending on your Go version:

Option 1: Use json.OrderedMap (Go 1.21+)

Go 1.21 introduced json.OrderedMap in the standard encoding/json package, designed specifically to retain the order of key-value pairs as they appear in the JSON input. Here's how to modify your code:

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
)

var GroupTestListUpdate = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    type Item struct {
        ID          string `json:"ID"`          // Match JSON key case exactly
        GroupName   string `json:"GroupName"`   // Fixed tag to align with JSON key
        NumQuestion string `json:"NumQuestion"` // Fixed tag
        Score       string `json:"Score"`       // Fixed tag
    }
    type Input struct {
        Name  string `json:"Name"`  // Fixed tag to align with JSON key
        Items []Item `json:"Items"` // Fixed tag (your original `array:"item"` was invalid)
    }

    // Use json.OrderedMap instead of regular map
    var objmap json.OrderedMap
    reqBody, err := ioutil.ReadAll(r.Body)
    if err != nil {
        http.Error(w, "can't read body", http.StatusBadRequest)
        return
    }

    err = json.Unmarshal(reqBody, &objmap)
    if err != nil {
        http.Error(w, "failed to parse JSON", http.StatusBadRequest)
        return
    }

    // Iterate in the original JSON order using Range
    objmap.Range(func(key string, value any) bool {
        // Convert the raw value to our Input struct
        inputBytes, _ := json.Marshal(value)
        var input Input
        json.Unmarshal(inputBytes, &input)
        
        fmt.Printf("Key: %s, Value: %+v\n", key, input)
        return true // Keep iterating through entries
    })
})

Note: I fixed the JSON tags in your structs—your original tags like array:"item" were invalid for the standard encoding/json package, which could have caused unexpected behavior. Tags need to match the exact key names in your JSON (they're case-sensitive!).

Option 2: Third-Party Library (For Go <1.21)

If you're stuck on an older Go version, use a well-maintained ordered map library like github.com/iancoleman/orderedmap. Here's a quick example:

import "github.com/iancoleman/orderedmap"

// ... inside your handler ...
var objmap *orderedmap.OrderedMap
err := json.Unmarshal(reqBody, &objmap)
if err != nil {
    http.Error(w, "failed to parse JSON", http.StatusBadRequest)
    return
}

// Iterate in JSON order
for _, key := range objmap.Keys() {
    val, _ := objmap.Get(key)
    // Convert val to Input struct as needed
}

2. Why Does the Map Order Stay the Same Every Time You Run the Code?

Great observation! Go's map traversal order isn't completely random, but it's also not guaranteed to be stable. Here's the breakdown:

  • Before Go 1.11: Every map traversal was fully randomized to prevent developers from accidentally relying on map order.
  • Starting with Go 1.12: The traversal order is fixed within a single program run, but it's randomized when the program starts up.

In your case, you're seeing the same order across runs likely due to a coincidence—maybe the hash values of your keys lead to the same ordering with the random seed generated on each startup. But this is not a behavior you can rely on! The Go team explicitly states that map order can change between Go versions, operating systems, or even different runs of the same program.

Always treat map order as unpredictable unless you're using an ordered map type like json.OrderedMap.

内容的提问来源于stack exchange,提问作者Tomson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 08:57:33