Strict JSON decoding with unknown fields

Go
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"strings"
)

// DecodeStrict decodes exactly one JSON value and rejects unknown fields
// and trailing data, which is useful when validating request payloads.
func DecodeStrict(data []byte, target any) error {
	decoder := json.NewDecoder(bytes.NewReader(data))
	decoder.DisallowUnknownFields()
	if err := decoder.Decode(target); err != nil {
		return fmt.Errorf("decode: %w", err)
	}
	if err := decoder.Decode(new(json.RawMessage)); err != io.EOF {
		if err == nil {
			return fmt.Errorf("decode: unexpected trailing data")
		}
		return fmt.Errorf("decode: trailing data: %w", err)
	}
	return nil
}

func main() {
	var payload struct {
		Name string `json:"name"`
		Age  int    `json:"age"`
	}
	fmt.Println(DecodeStrict([]byte(`{"name":"Ada","age":36}`), &payload))
	err := DecodeStrict([]byte(`{"name":"Ada","age":36,"admin":true}`), &payload)
	fmt.Println(strings.Contains(err.Error(), "unknown field"))
}