jsonschema: emit properties:{} again — value receiver + no omitempty

MarshalJSON had drifted to a pointer receiver while Properties gained
`,omitempty`. Together those defeated the nil->empty-map fill: encoding/json
never invokes a pointer-receiver MarshalJSON on non-addressable values (map
entries, a Definition passed by value), and omitempty drops the empty map even
when it does. Nested schemas therefore lost the "properties":{} that OpenAI
requires on object schemas — the exact bug #419/#434 fixed.

Value receiver restores the guarantee for map entries and by-value marshals;
dropping omitempty lets the filled empty map through. TestDefinition_MarshalJSON
(got and gotPtr) passes again.

Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
2026-07-27 15:43:22 -07:00
co-authored by Hanzo Dev
parent 88762272c3
commit 6168c092c9
+3 -3
View File
@@ -35,7 +35,7 @@ type Definition struct {
// one element, where each element is unique. You will probably only use this with strings.
Enum []string `json:"enum,omitempty"`
// Properties describes the properties of an object, if the schema type is Object.
Properties map[string]Definition `json:"properties,omitempty"`
Properties map[string]Definition `json:"properties"`
// Required specifies which properties are required, if the schema type is Object.
Required []string `json:"required,omitempty"`
// Items specifies which data type an array contains, if the schema type is Array.
@@ -48,7 +48,7 @@ type Definition struct {
AdditionalProperties any `json:"additionalProperties,omitempty"`
}
func (d *Definition) MarshalJSON() ([]byte, error) {
func (d Definition) MarshalJSON() ([]byte, error) {
if d.Properties == nil {
d.Properties = make(map[string]Definition)
}
@@ -56,7 +56,7 @@ func (d *Definition) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Alias
}{
Alias: (Alias)(*d),
Alias: (Alias)(d),
})
}