People land here from searches like golang map to json, go map to json, golang convert map to json string, or golang print map as json — all of that is encoding/json in practice. Marshal turns a map into bytes you can cast to a JSON string; json.Unmarshal handles json to map golang and golang json to map when you parse API or file data back into a map[string]any (or a struct). This guide uses small main examples for marshal, encoder output, indentation, and reverse parsing. For larger typed documents, pair this with JSON unmarshal in Go.
Tested with Go 1.24 on Linux.
Convert a map to JSON (json.Marshal)
json.Marshal turns any JSON-marshalable value into a []byte and an error. For a map, use string keys (map[string]T); that matches JSON objects. To get a golang map to json string, convert the bytes:
package main
import (
"encoding/json"
"fmt"
)
func main() {
m := map[string]int{"one": 1, "two": 2, "three": 3}
b, err := json.Marshal(m)
if err != nil {
fmt.Println("marshal:", err)
return
}
fmt.Println(string(b))
}You should see one line of JSON with the three keys (order may vary between runs because map iteration is not sorted).
Write JSON with json.NewEncoder (streams and io.Writer)
json.NewEncoder(w).Encode(v) writes JSON to w and appends a newline. Use it for HTTP responses, files, or a bytes.Buffer when you prefer streaming over building a single []byte.
package main
import (
"bytes"
"encoding/json"
"fmt"
)
func main() {
m := map[string]int{"one": 1, "two": 2, "three": 3}
var buf bytes.Buffer
enc := json.NewEncoder(&buf)
if err := enc.Encode(m); err != nil {
fmt.Println("encode:", err)
return
}
fmt.Print(buf.String())
}The buffer ends with a trailing newline from Encode.
Pretty-print: json.MarshalIndent and indented encoders
To golang print map as json in a readable shape, use json.MarshalIndent(v, prefix, indent) or set indent on an encoder.
package main
import (
"encoding/json"
"fmt"
)
func main() {
m := map[string]any{
"name": "Some User",
"age": 35,
"address": map[string]string{
"street": "Random St",
"city": "Some town",
"state": "Some state",
"zip": "12345",
},
}
b, err := json.MarshalIndent(m, "", " ")
if err != nil {
fmt.Println("marshal:", err)
return
}
fmt.Println(string(b))
}You should see nested JSON with two-space indentation.
JSON to map: json.Unmarshal
To parse JSON back into a map — the reverse of map to JSON — use json.Unmarshal on your bytes. A flexible choice is map[string]any so nested JSON objects become nested maps:
package main
import (
"encoding/json"
"fmt"
)
func main() {
const s = `{"name":"Ada","score":99,"ok":true}`
var out map[string]any
if err := json.Unmarshal([]byte(s), &out); err != nil {
fmt.Println("unmarshal:", err)
return
}
fmt.Println(out["name"], out["score"], out["ok"])
}You should see Ada, 99, and true (numeric JSON values decode as float64 in any; use a struct or json.Decoder with UseNumber if you need exact number handling). For stable field types and validation, unmarshal into a struct instead; see JSON unmarshal in Go.
Summary
You now have a practical path for map to JSON and back with encoding/json: json.Marshal plus string([]byte) for a compact JSON string, json.NewEncoder when you already have an io.Writer, and json.MarshalIndent (or Encoder.SetIndent) when you want readable JSON in logs or responses. Parsing uses json.Unmarshal into map[string]any for flexible shapes, or into structs when you want typed fields and clearer validation — see the linked unmarshal guide. Remember that JSON numbers stored in any decode as float64 unless you opt into different handling, and that map key order in generated JSON is not sorted. Check marshal and unmarshal errors on every call before trusting the result.
References
- Package json —
Marshal,Unmarshal,Encoder,Decoder - Convert Go map to JSON — Stack Overflow discussion
- JSON unmarshal in Go — structs, tags, and edge cases on this site

