From ff3e44eb84873206ac834093495f67c8e51fd8ae Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 23 Oct 2026 22:12:22 +0000 Subject: [PATCH] fix: drop misleading extensions json tag on ProblemDetails MarshalJSON/UnmarshalJSON flatten extension members to the top level, so the nested "extensions" tag was never used. Closes #19 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01FHBdej3KvFACHzafbEhw7C --- problem_details.go | 15 +++++++++------ problem_details_test.go | 25 +++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/problem_details.go b/problem_details.go index a3da08b..9422406 100644 --- a/problem_details.go +++ b/problem_details.go @@ -10,12 +10,15 @@ const BlankURL = "about:blank" // ProblemDetails conforms to RFC 9457, providing a standard format for describing errors in HTTP APIs. type ProblemDetails struct { - Type string `json:"type"` - Title string `json:"title"` - Status int `json:"status"` - Detail string `json:"detail,omitempty"` - Instance string `json:"instance,omitempty"` - Extensions map[string]interface{} `json:"extensions,omitempty"` + Type string `json:"type"` + Title string `json:"title"` + Status int `json:"status"` + Detail string `json:"detail,omitempty"` + Instance string `json:"instance,omitempty"` + // Extensions holds RFC 9457 extension members. MarshalJSON and + // UnmarshalJSON flatten them to the top level; there is no nested + // "extensions" object on the wire. + Extensions map[string]interface{} `json:"-"` } // ValidationErrorDetail provides structured details about a single validation error. diff --git a/problem_details_test.go b/problem_details_test.go index 6f1c7be..793a4e5 100644 --- a/problem_details_test.go +++ b/problem_details_test.go @@ -118,3 +118,28 @@ func TestProblemDetailsMarshalJSONFlattensExtensions(t *testing.T) { t.Fatalf("expected trace_id extension, got %#v", payload["trace_id"]) } } + +func TestProblemDetailsMarshalJSONHasNoNestedExtensions(t *testing.T) { + t.Parallel() + + body, err := json.Marshal(ProblemDetails{ + Type: BlankURL, + Title: "Bad Request", + Status: 400, + Extensions: map[string]interface{}{"code": "E1"}, + }) + if err != nil { + t.Fatalf("marshal: %v", err) + } + + var payload map[string]any + if err := json.Unmarshal(body, &payload); err != nil { + t.Fatalf("unmarshal: %v", err) + } + if _, ok := payload["extensions"]; ok { + t.Fatalf("unexpected nested extensions key: %s", body) + } + if payload["code"] != "E1" { + t.Fatalf("expected flattened extension, got %s", body) + } +}