戈朗。映射到 JSON,但保留键顺序
Golang. Map to JSON, but preserve the key order
我有一个地图对象,当它使用 json.Marshal(myMapObjct)
序列化时,Golang 会按字母顺序对键进行排序,这会导致数据处理方式出现问题。一旦将 JSON 结构创建为字节片,保留键顺序很重要。是否有可能以这种方式序列化它,或者我是否需要为这种特定的边缘情况编写自己的序列化程序?
这是负责生成 JSON 结构的代码片段:
// 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
}
根据建议,我提供了一个不同的结构来修复代码。
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
}
我有一个地图对象,当它使用 json.Marshal(myMapObjct)
序列化时,Golang 会按字母顺序对键进行排序,这会导致数据处理方式出现问题。一旦将 JSON 结构创建为字节片,保留键顺序很重要。是否有可能以这种方式序列化它,或者我是否需要为这种特定的边缘情况编写自己的序列化程序?
这是负责生成 JSON 结构的代码片段:
// 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
}
根据建议,我提供了一个不同的结构来修复代码。
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
}