I've a map object and when it's serialized using json.Marshal(myMapObjct)
the Golang sorts the keys in alphabetic order, which is causing issues on how the data is being processed. It's important to preserve the key ordering once the JSON structure has been created into a slice of bytes. Is it possible to serialize it in such a way or do I need to write my own serializer for this specific edge case?
This is the code snippet responsible for generating the JSON structure:
// 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
}
As per suggestions I'm providing a different structure which fixes the code.
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
}