How to Validate JSON Against a Schema in Go (and When to Skip Writing Go for It)
Go’s standard library encoding/json will happily unmarshal malformed-shape JSON into a struct with zero values and no error — which is exactly the failure mode that makes schema validation worth doing explicitly, rather than trusting Unmarshal’s silence.
Why Unmarshal alone isn’t validation
type User struct {
ID int `json:"id"`
Name string `json:"name"`
}
var u User
json.Unmarshal([]byte(`{"name": "Alice"}`), &u) // no error — u.ID is just 0
Missing fields don’t error — they silently become the zero value (0, "", false, nil). If id is actually required, this bug ships silently until something downstream breaks on an ID of 0. encoding/json validates syntax, not shape.
Schema validation with gojsonschema
import "github.com/xeipuuv/gojsonschema"
schemaLoader := gojsonschema.NewStringLoader(schemaJSON)
docLoader := gojsonschema.NewStringLoader(payloadJSON)
result, err := gojsonschema.Validate(schemaLoader, docLoader)
if !result.Valid() {
for _, e := range result.Errors() {
fmt.Println(e.String()) // e.g. "id is required"
}
}
This actually enforces required fields, types, string patterns, and enums — the checks Unmarshal skips. The cost is writing and maintaining a JSON Schema document alongside your Go types, which is one more artifact to keep in sync when the shape changes.
Going the other direction: struct from JSON
If you’re the one consuming an API and just need a Go struct that matches its response shape, hand-writing field names, JSON tags, and guessing at types (is that number an int or should it be float64? is that field ever absent, meaning it needs to be a pointer?) from a sample payload is tedious and error-prone. Our Go Struct Generator takes a JSON sample and produces the struct definition with tags already attached — a faster and more accurate starting point than typing it by hand, even if you then hand-tune a few fields (like widening an int to int64, or making an optional field a pointer).
When you just need a quick check, no Go involved
Setting up go run with an import just to eyeball whether a JSON blob matches an expected shape is overhead for what’s often a 30-second question. JSON Schema Validator runs the same category of check — required fields, types, enums — directly in the browser with immediate, readable error output, no go.mod required. Reach for actual Go code when the validation needs to run as part of your service; reach for the browser tool when you’re just sanity-checking a payload by hand.
The quick decision
- Validating untrusted input inside a running Go service →
gojsonschema(or similar), so the check is enforced in code, not just eyeballed once - Need a Go struct to consume a JSON API → Go Struct Generator for the first draft
- Just checking a pasted blob against expected shape, no service involved → JSON Schema Validator