Skip to content

Update unmarshalJSON to handle decoder cases #420

@brion-fuller

Description

@brion-fuller

BUG:
When I want to error for unknown fields, I cannot do that with the current UnmarshalJSON functions on the created type.

Example:

package main

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

type Person struct {
	Name string `json:"name"`
	Age  int    `json:"age"`
}

func main() {
	jsonString := `{"name": "John Doe", "age": 30, "city": "New York"}`
	var person Person

	decoder := json.NewDecoder(strings.NewReader(jsonString))
	decoder.DisallowUnknownFields()

	err := decoder.Decode(&person)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}

	fmt.Printf("Person: %+v\n", person)
}

Today, UnmarshalJSON calls directly json.Unmarshal which ignores the cases when someone is using json.Decoder.
We should update the UnmarshalJSON functions to create a NewDecoder. I have tested this with my own modified version and works for both cases. An update function could look something like this. I pulled this from how go's native unmarshal function operates.

func (j *T) UnmarshalJSON(b []byte) error {
	d := json.NewDecoder(bytes.NewReader(b))

	var raw map[string]interface{}
	if err := d.Decode(&raw); err != nil {
		return err
	}
	if _, ok := raw["key"]; raw != nil && !ok {
		return fmt.Errorf("field %f in T: required")
	}
	type Plain T
	var plain Plain
	if err := d.Decode(&plain); err != nil {
		return err
	}
	*j = T(plain)
	return nil
}

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions