openai/openai-go

Public

mirrored fromhttps://github.com/openai/openai-goAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
9314b6c3bd913e265f75d0a49600b60d6d25d8ae

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

packages/param/param.go

186lines · modecode

1package param
2
3import (
4 "encoding/json"
5 "github.com/openai/openai-go/v3/internal/encoding/json/sentinel"
6 "reflect"
7)
8
9// NullStruct is used to set a struct to the JSON value null.
10// Check for null structs with [IsNull].
11//
12// Only the first type parameter should be provided,
13// the type PtrT will be inferred.
14//
15// json.Marshal(param.NullStruct[MyStruct]()) -> 'null'
16//
17// To send null to an [Opt] field use [Null].
18func NullStruct[T ParamStruct, PtrT InferPtr[T]]() T {
19 var t T
20 pt := PtrT(&t)
21 pt.setMetadata(nil)
22 return *pt
23}
24
25// Override replaces the value of a struct with any type.
26//
27// Only the first type parameter should be provided,
28// the type PtrT will be inferred.
29//
30// It's often useful for providing raw JSON
31//
32// param.Override[MyStruct](json.RawMessage(`{"foo": "bar"}`))
33//
34// The public fields of the returned struct T will be unset.
35//
36// To override a specific field in a struct, use its [SetExtraFields] method.
37func Override[T ParamStruct, PtrT InferPtr[T]](v any) T {
38 var t T
39 pt := PtrT(&t)
40 pt.setMetadata(v)
41 return *pt
42}
43
44// SetJSON configures a param struct to serialize with the provided raw JSON data.
45// Use this when you have existing JSON that you want to send as request parameters.
46//
47// var req example.NewUserParams
48// var rawJSON = []byte(`{"name": "...", "age": 40}`)
49// param.SetJSON(rawJSON, &req)
50// res, err := client.Users.New(ctx, req)
51//
52// Note: The struct's existing fields will be ignored; only the provided JSON is serialized.
53func SetJSON(rawJSON []byte, ptr anyParamStruct) {
54 ptr.setMetadata(json.RawMessage(rawJSON))
55}
56
57// IsOmitted returns true if v is the zero value of its type.
58//
59// If IsOmitted is true, and the field uses a `json:"...,omitzero"` tag,
60// the field will be omitted from the request.
61//
62// If v is set explicitly to the JSON value "null", IsOmitted returns false.
63func IsOmitted(v any) bool {
64 if v == nil {
65 return false
66 }
67 if o, ok := v.(Optional); ok {
68 return o.isZero()
69 }
70 return reflect.ValueOf(v).IsZero()
71}
72
73// IsNull returns true if v was set to the JSON value null.
74//
75// To set a param to null use [NullStruct], [Null], [NullMap], or [NullSlice]
76// depending on the type of v.
77//
78// IsNull returns false if the value is omitted.
79func IsNull[T any](v T) bool {
80 if nullable, ok := any(v).(ParamNullable); ok {
81 return nullable.null()
82 }
83
84 switch reflect.TypeOf(v).Kind() {
85 case reflect.Slice, reflect.Map:
86 return sentinel.IsNull(v)
87 }
88
89 return false
90}
91
92// ParamNullable encapsulates all structs in parameters,
93// and all [Opt] types in parameters.
94type ParamNullable interface {
95 null() bool
96}
97
98// ParamStruct represents the set of all structs that are
99// used in API parameters, by convention these usually end in
100// "Params" or "Param".
101type ParamStruct interface {
102 Overrides() (any, bool)
103 null() bool
104 extraFields() map[string]any
105}
106
107// A pointer to ParamStruct
108type anyParamStruct interface {
109 setMetadata(any)
110}
111
112// This is an implementation detail and should never be explicitly set.
113type InferPtr[T ParamStruct] interface {
114 setMetadata(any)
115 *T
116}
117
118// APIObject should be embedded in api object fields, preferably using an alias to make private
119type APIObject struct{ metadata }
120
121// APIUnion should be embedded in all api unions fields, preferably using an alias to make private
122type APIUnion struct{ metadata }
123
124// Overrides returns the value of the struct when it is created with
125// [Override], the second argument helps differentiate an explicit null.
126func (m metadata) Overrides() (any, bool) {
127 if _, ok := m.any.(metadataExtraFields); ok {
128 return nil, false
129 }
130 return m.any, m.any != nil
131}
132
133// ExtraFields returns the extra fields added to the JSON object.
134func (m metadata) ExtraFields() map[string]any {
135 if extras, ok := m.any.(metadataExtraFields); ok {
136 return extras
137 }
138 return nil
139}
140
141// Omit can be used with [metadata.SetExtraFields] to ensure that a
142// required field is omitted. This is useful as an escape hatch for
143// when a required is unwanted for some unexpected reason.
144const Omit forceOmit = -1
145
146// SetExtraFields adds extra fields to the JSON object.
147//
148// SetExtraFields will override any existing fields with the same key.
149// For security reasons, ensure this is only used with trusted input data.
150//
151// To intentionally omit a required field, use [Omit].
152//
153// foo.SetExtraFields(map[string]any{"bar": Omit})
154//
155// If the struct already contains the field ExtraFields, then this
156// method will have no effect.
157func (m *metadata) SetExtraFields(extraFields map[string]any) {
158 m.any = metadataExtraFields(extraFields)
159}
160
161// extraFields aliases [metadata.ExtraFields] to avoid name collisions.
162func (m metadata) extraFields() map[string]any { return m.ExtraFields() }
163
164func (m metadata) null() bool {
165 if _, ok := m.any.(metadataNull); ok {
166 return true
167 }
168
169 if msg, ok := m.any.(json.RawMessage); ok {
170 return string(msg) == "null"
171 }
172
173 return false
174}
175
176type metadata struct{ any }
177type metadataNull struct{}
178type metadataExtraFields map[string]any
179
180func (m *metadata) setMetadata(override any) {
181 if override == nil {
182 m.any = metadataNull{}
183 return
184 }
185 m.any = override
186}
187