【问题标题】:Golang. Map to JSON, but preserve the key order戈朗。映射到 JSON,但保留键顺序
【发布时间】:2022-01-08 17:21:48
【问题描述】:

我有一个地图对象,当它使用json.Marshal(myMapObjct) 序列化时,Golang 会按字母顺序对键进行排序,这会导致数据处理方式出现问题。将 JSON 结构创建为字节切片后,保留键顺序很重要。是否可以以这种方式对其进行序列化,或者我是否需要为这种特定的边缘情况编写自己的序列化程序?

这是负责生成JSON结构的代码sn-p:

// serializedTraffic wraps around naturalTraffic and serializes map to string.
func serializedTraffic(payload string) (string, error) {
    trafficMap := naturalTraffic(string(payload))
    traffic, err := json.Marshal(trafficMap)
    return string(traffic), err
}

    // naturalTraffic obfuscates 'payload' into JSON-like structure.
func naturalTraffic(payload string) map[string]string {
    // Decide on how many keys there will be in the JSON structure.
    indexChar := 0
    maxChars := 126
    minChars := 16

    var jsonObject = make(map[string]string)

    // Build the JSON structure.
    for indexChar < len(payload) {
        rand.Seed(time.Now().UnixNano())
        chunkSize := rand.Intn(maxChars-minChars) + minChars
        if len(payload) < indexChar+chunkSize {
            chunkSize = len(payload) - indexChar
        }
        key := randomPopularWord()
        jsonObject[key] = base64.StdEncoding.EncodeToString([]byte(payload[indexChar : indexChar+chunkSize]))
        indexChar += chunkSize
    }

    return jsonObject
}

【问题讨论】:

  • 您要订购吗?然后使用结构,因为 Go 中的映射是无序的,这是设计的。参见Map types spec“地图是一组无序元素...”.
  • 不,那是 json.Marshal 进行排序,地图是无序的。您可以在此 page 上搜索“排序”一词,它解释了为什么您要在生成的 json 对象中排序映射键。
  • 将键和值存储在切片中。使用 json.Encoder 将切片编码为 JSON 对象。使用Encoder.Encode 方法写入键和值。
  • 如果不知道数据的来源和所需的顺序是什么,很难提供有效的建议。如您所知,Go 地图是无序的。因此,如果您从围棋地图开始,就控制顺序而言,您已经不走运了。
  • 编辑问题以显示您如何存储有序键和值。

标签: json go serialization json-serialization


【解决方案1】:

根据建议,我提供了一种不同的结构来修复代码。

    type elem struct{ key, val string }

    type object []elem

    func (o object) MarshalJSON() (out []byte, err error) {
        if o == nil {
            return []byte(`null`), nil
        }
        if len(o) == 0 {
            return []byte(`{}`), nil
        }

        out = append(out, '{')
        for _, e := range o {
            key, err := json.Marshal(e.key)
            if err != nil {
                return nil, err
            }
            val, err := json.Marshal(e.val)
            if err != nil {
                return nil, err
            }
            out = append(out, key...)
            out = append(out, ':')
            out = append(out, val...)
            out = append(out, ',')
        }
        // replace last ',' with '}'
        out[len(out)-1] = '}'
        return out, nil
    }

    // serializedTraffic wraps around naturalTraffic and serializes map to string.
    func serializedTraffic(payload string) (string, error) {
        trafficMap := naturalTraffic(string(payload))
        traffic, err := trafficMap.MarshalJSON()
        return string(traffic), err
    }

    // naturalTraffic obfuscates 'payload' into JSON-like structure.
    func naturalTraffic(payload string) object {
        // Decide on how many keys there will be in the JSON structure.
        indexChar := 0
        maxChars := 126
        minChars := 16

        var jsonObject object

        // Build the JSON structure.
        for indexChar < len(payload) {
            rand.Seed(time.Now().UnixNano())
            chunkSize := rand.Intn(maxChars-minChars) + minChars
            if len(payload) < indexChar+chunkSize {
                chunkSize = len(payload) - indexChar
            }
            key := randomPopularWord()
            jsonObject = append(jsonObject, elem{
                key: key,
                val: base64.StdEncoding.EncodeToString([]byte(payload[indexChar : indexChar+chunkSize])),
            })
            indexChar += chunkSize
        }

        return jsonObject
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-02-11
    • 1970-01-01
    • 2012-06-23
    • 1970-01-01
    • 1970-01-01
    • 2014-04-18
    • 1970-01-01
    • 2010-12-26
    相关资源
    最近更新 更多