jsongogofmt

Runtime error when parsing JSON array and map elements with trailing commas using Go


Dave Cheney, one of the leading subject matter experts on Go, wrote: "When initializing a variable with a composite literal, Go requires that each line of the composite literal end with a comma, even the last line of your declaration. This is the result of the semicolon rule."

However, when I am trying to apply that beautiful rule to JSON text, the parser doesn't seem to agree with this philosophy. In the code below, removing the comma works. Is there a fix for this so I can just see one line change when I add elements in my diffs?

package main

import (
    "fmt"
    "encoding/json"
)

type jsonobject struct {
    Objects []ObjectType `json:"objects"`
}

type ObjectType struct {
    Name string `json:"name"`
}

func main() {
    bytes := []byte(`{ "objects": 
        [ 
            {"name": "foo"}, // REMOVE THE COMMA TO MAKE THE CODE WORK!
        ]}`)
    jsontype := &jsonobject{}
    json.Unmarshal(bytes, &jsontype)
    fmt.Printf("Results: %v\n", jsontype.Objects[0].Name) // panic: runtime error: index out of range
}

Solution

  • There is not. The JSON specification does not allow a trailing comma.

    This is not a valid JSON:

    { "objects": 
        [ 
            {"name": "foo"},
    ]}
    

    It's a Go syntax that you need to use a comma if the enumeration is not closed on the line (more on this), e.g.:

    // Slice literal:
    s := []int {
        1,
        2,
    }
    
    // Function call:
    fmt.Println(
        "Slice:",
        s,
    )
    

    Even if you could "convince" one specific JSON parser to silently swallow it, other, valid JSON parsers would report an error, rightfully. Don't do it.