Serialize a map using a specific order

For that specific requirement you really don't need to use json.Marshal at all, you can simply implement your own function like this:

type OrderedMap map[string]string

func (om OrderedMap) ToJson(order ...string) string {
    buf := &bytes.Buffer{}
    buf.Write([]byte{'{', '\n'})
    l := len(order)
    for i, k := range order {
        fmt.Fprintf(buf, "\t\"%s\": \"%v\"", k, om[k])
        if i < l-1 {
            buf.WriteByte(',')
        }
        buf.WriteByte('\n')
    }
    buf.Write([]byte{'}', '\n'})
    return buf.String()
}
func main() {
    om := OrderedMap{
        "age":  "20",
        "name": "John",
    }
    fmt.Println(om.ToJson("name", "age"))
}

Probably the easiest solution: https://github.com/iancoleman/orderedmap

Although it might be slow as it's mentioned here


You need to implement the json.Marshaler interface on a custom type. This has the advantage of playing well within other struct types.

Sorry, you're always going to have to write a little bit of JSON encoding code.

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "log"
)

type KeyVal struct {
    Key string
    Val interface{}
}

// Define an ordered map
type OrderedMap []KeyVal

// Implement the json.Marshaler interface
func (omap OrderedMap) MarshalJSON() ([]byte, error) {
    var buf bytes.Buffer

    buf.WriteString("{")
    for i, kv := range omap {
        if i != 0 {
            buf.WriteString(",")
        }
        // marshal key
        key, err := json.Marshal(kv.Key)
        if err != nil {
            return nil, err
        }
        buf.Write(key)
        buf.WriteString(":")
        // marshal value
        val, err := json.Marshal(kv.Val)
        if err != nil {
            return nil, err
        }
        buf.Write(val)
    }

    buf.WriteString("}")
    return buf.Bytes(), nil
}

func main() {
    dict := map[string]interface{}{
        "orderedMap": OrderedMap{
            {"name", "John"},
            {"age", 20},
        },
    }
    dump, err := json.Marshal(dict)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("%s\n", dump)
}

Outputs

{"orderedMap":{"name":"John","age":20}}