From 6eb6748b8be7a332d504b474bfde96f76d361414 Mon Sep 17 00:00:00 2001 From: Aditya Kar Date: Tue, 30 Sep 2025 23:43:59 -0400 Subject: [PATCH 1/2] fix: handle param.Opt types in ChatCompletionToolChoiceOptionUnionParam unmarshaling This commit addresses issue #520 where the JSON unmarshaling fails for ChatCompletionToolChoiceOptionUnionParam when encountering OfAuto field with param.Opt[string] type. The decoder.field.Type.Elem() method was calling .Elem() on param.Opt[string] which is not a pointer type, causing unmarshaling to fail. Modified files and changes: - chatcompletion.go: * Added custom UnmarshalJSON method for ChatCompletionToolChoiceOptionUnionParam * Implemented proper handling of simple string values for OfAuto field * Added discriminated object unmarshaling based on "type" field * Added support for "function", "allowed_tools", and "custom" types * Replaced generic apijson.UnmarshalRoot call with type-specific handling This fix ensures that the union parameter can properly unmarshal both string values and complex objects without encountering type reflection errors when dealing with param.Opt types. --- chatcompletion.go | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/chatcompletion.go b/chatcompletion.go index 962b69d0..b6b3bfbf 100644 --- a/chatcompletion.go +++ b/chatcompletion.go @@ -2689,8 +2689,42 @@ type ChatCompletionToolChoiceOptionUnionParam struct { func (u ChatCompletionToolChoiceOptionUnionParam) MarshalJSON() ([]byte, error) { return param.MarshalUnion(u, u.OfAuto, u.OfAllowedTools, u.OfFunctionToolChoice, u.OfCustomToolChoice) } + +// https://github.com/openai/openai-go/issues/520 +// The issue: decoder.field.Type.Elem() calls .Elem() on the field type. When it encounters the OfAuto field (which is param.Opt[string]), calling .Elem() fails because param.Opt[string] is not a pointer type. +// Solution: either handle it here or modify the Elem() code to handle param.Opt types. func (u *ChatCompletionToolChoiceOptionUnionParam) UnmarshalJSON(data []byte) error { - return apijson.UnmarshalRoot(data, u) + // Handle simple string values first + var str string + if json.Unmarshal(data, &str) == nil { + u.OfAuto = param.Opt[string]{Value: str} + return nil + } + + // Handle discriminated objects + var obj struct { + Type string `json:"type"` + } + if json.Unmarshal(data, &obj) != nil { + return nil // Invalid format, but don't error + } + + // Unmarshal based on type using a single apijson.UnmarshalRoot call + switch obj.Type { + case "function": + var v ChatCompletionNamedToolChoiceParam + apijson.UnmarshalRoot(data, &v) + u.OfFunctionToolChoice = &v + case "allowed_tools": + var v ChatCompletionAllowedToolChoiceParam + apijson.UnmarshalRoot(data, &v) + u.OfAllowedTools = &v + case "custom": + var v ChatCompletionNamedToolChoiceCustomParam + apijson.UnmarshalRoot(data, &v) + u.OfCustomToolChoice = &v + } + return nil } func (u *ChatCompletionToolChoiceOptionUnionParam) asAny() any { From 3fcb41f16c805e3a9a724cc25afc6a96c3daafa1 Mon Sep 17 00:00:00 2001 From: Aditya Kar Date: Tue, 30 Sep 2025 23:53:46 -0400 Subject: [PATCH 2/2] fix: clarify comments regarding param.Opt handling in UnmarshalJSON method --- chatcompletion.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chatcompletion.go b/chatcompletion.go index b6b3bfbf..362d0d86 100644 --- a/chatcompletion.go +++ b/chatcompletion.go @@ -2691,8 +2691,8 @@ func (u ChatCompletionToolChoiceOptionUnionParam) MarshalJSON() ([]byte, error) } // https://github.com/openai/openai-go/issues/520 -// The issue: decoder.field.Type.Elem() calls .Elem() on the field type. When it encounters the OfAuto field (which is param.Opt[string]), calling .Elem() fails because param.Opt[string] is not a pointer type. -// Solution: either handle it here or modify the Elem() code to handle param.Opt types. +// The issue: in union.go, newStructUnionDecoder method -> decoder.field.Type.Elem() calls .Elem() on the field type. When it encounters the OfAuto field (which is param.Opt[string]), calling .Elem() fails because param.Opt[string] is not a pointer type. +// Solution: either handle it here or modify the newStructUnionDecoder code to handle param.Opt types. func (u *ChatCompletionToolChoiceOptionUnionParam) UnmarshalJSON(data []byte) error { // Handle simple string values first var str string