github.com/anthropics/anthropic-sdk-go@v1.70.1/packages/param/param.go (about) 1 package param 2 3 import ( 4 "encoding/json" 5 "github.com/anthropics/anthropic-sdk-go/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]. 18 func 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. 37 func 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. 53 func 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. 63 func 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. 79 func 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. 94 type 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". 101 type ParamStruct interface { 102 Overrides() (any, bool) 103 null() bool 104 extraFields() map[string]any 105 } 106 107 // A pointer to ParamStruct 108 type anyParamStruct interface { 109 setMetadata(any) 110 } 111 112 // This is an implementation detail and should never be explicitly set. 113 type 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 119 type APIObject struct{ metadata } 120 121 // APIUnion should be embedded in all api unions fields, preferably using an alias to make private 122 type 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. 126 func (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. 134 func (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. 144 const 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. 157 func (m *metadata) SetExtraFields(extraFields map[string]any) { 158 m.any = metadataExtraFields(extraFields) 159 } 160 161 // extraFields aliases [metadata.ExtraFields] to avoid name collisions. 162 func (m metadata) extraFields() map[string]any { return m.ExtraFields() } 163 164 func (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 176 type metadata struct{ any } 177 type metadataNull struct{} 178 type metadataExtraFields map[string]any 179 180 func (m *metadata) setMetadata(override any) { 181 if override == nil { 182 m.any = metadataNull{} 183 return 184 } 185 m.any = override 186 }