package main import ( "bytes" "encoding/json" "fmt" "io" "os" "testing" ) const indent = " " // Pretty formats JSON with stable two-space indentation. func Pretty(src []byte) ([]byte, error) { var value any dec := json.NewDecoder(bytes.NewReader(src)) dec.UseNumber() if err := dec.Decode(&value); err != nil { return nil, err } if dec.Decode(&struct{}{}) != io.EOF { return nil, fmt.Errorf("input contains multiple JSON values") } return json.MarshalIndent(value, "", indent) } // PrettyString is a small convenience wrapper around Pretty. func PrettyString(src string) (string, error) { out, err := Pretty([]byte(src)) if err != nil { return "", err } return string(out), nil } func main() { in, err := io.ReadAll(os.Stdin) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } out, err := Pretty(in) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } os.Stdout.Write(out) os.Stdout.Write([]byte("\n")) } func TestPrettyObject(t *testing.T) { got, err := PrettyString(`{"name":"Ada","nums":[1,2],"ok":true}`) if err != nil { t.Fatal(err) } want := "{\n \"name\": \"Ada\",\n \"nums\": [\n 1,\n 2\n ],\n \"ok\": true\n}" if got != want { t.Fatalf("PrettyString() = %q, want %q", got, want) } } func TestPrettyRejectsTrailingValue(t *testing.T) { if _, err := PrettyString(`{"ok":true} {"extra":true}`); err == nil { t.Fatal("expected an error for multiple JSON values") } }