github.com/anthropics/anthropic-sdk-go@v1.70.1/internal/apijson/encoder.go (about) 1 package apijson 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "reflect" 8 "sort" 9 "strconv" 10 "strings" 11 "sync" 12 "time" 13 14 "github.com/tidwall/sjson" 15 16 shimjson "github.com/anthropics/anthropic-sdk-go/internal/encoding/json" 17 ) 18 19 var encoders sync.Map // map[encoderEntry]encoderFunc 20 21 // If we want to set a literal key value into JSON using sjson, we need to make sure it doesn't have 22 // special characters that sjson interprets as a path. 23 var EscapeSJSONKey = strings.NewReplacer("\\", "\\\\", "|", "\\|", "#", "\\#", "@", "\\@", "*", "\\*", ".", "\\.", ":", "\\:", "?", "\\?").Replace 24 25 func Marshal(value any) ([]byte, error) { 26 e := &encoder{dateFormat: time.RFC3339} 27 return e.marshal(value) 28 } 29 30 func MarshalRoot(value any) ([]byte, error) { 31 e := &encoder{root: true, dateFormat: time.RFC3339} 32 return e.marshal(value) 33 } 34 35 type encoder struct { 36 dateFormat string 37 root bool 38 } 39 40 type encoderFunc func(value reflect.Value) ([]byte, error) 41 42 type encoderField struct { 43 tag parsedStructTag 44 fn encoderFunc 45 idx []int 46 } 47 48 type encoderEntry struct { 49 typ reflect.Type 50 dateFormat string 51 root bool 52 } 53 54 func (e *encoder) marshal(value any) ([]byte, error) { 55 val := reflect.ValueOf(value) 56 if !val.IsValid() { 57 return nil, nil 58 } 59 typ := val.Type() 60 enc := e.typeEncoder(typ) 61 return enc(val) 62 } 63 64 func (e *encoder) typeEncoder(t reflect.Type) encoderFunc { 65 entry := encoderEntry{ 66 typ: t, 67 dateFormat: e.dateFormat, 68 root: e.root, 69 } 70 71 if fi, ok := encoders.Load(entry); ok { 72 return fi.(encoderFunc) 73 } 74 75 // To deal with recursive types, populate the map with an 76 // indirect func before we build it. This type waits on the 77 // real func (f) to be ready and then calls it. This indirect 78 // func is only used for recursive types. 79 var ( 80 wg sync.WaitGroup 81 f encoderFunc 82 ) 83 wg.Add(1) 84 fi, loaded := encoders.LoadOrStore(entry, encoderFunc(func(v reflect.Value) ([]byte, error) { 85 wg.Wait() 86 return f(v) 87 })) 88 if loaded { 89 return fi.(encoderFunc) 90 } 91 92 // Compute the real encoder and replace the indirect func with it. 93 f = e.newTypeEncoder(t) 94 wg.Done() 95 encoders.Store(entry, f) 96 return f 97 } 98 99 func marshalerEncoder(v reflect.Value) ([]byte, error) { 100 return v.Interface().(json.Marshaler).MarshalJSON() 101 } 102 103 func indirectMarshalerEncoder(v reflect.Value) ([]byte, error) { 104 return v.Addr().Interface().(json.Marshaler).MarshalJSON() 105 } 106 107 func (e *encoder) newTypeEncoder(t reflect.Type) encoderFunc { 108 if t.ConvertibleTo(reflect.TypeOf(time.Time{})) { 109 return e.newTimeTypeEncoder() 110 } 111 if !e.root && t.Implements(reflect.TypeOf((*json.Marshaler)(nil)).Elem()) { 112 return marshalerEncoder 113 } 114 if !e.root && reflect.PointerTo(t).Implements(reflect.TypeOf((*json.Marshaler)(nil)).Elem()) { 115 return indirectMarshalerEncoder 116 } 117 e.root = false 118 switch t.Kind() { 119 case reflect.Pointer: 120 inner := t.Elem() 121 122 innerEncoder := e.typeEncoder(inner) 123 return func(v reflect.Value) ([]byte, error) { 124 if !v.IsValid() || v.IsNil() { 125 return nil, nil 126 } 127 return innerEncoder(v.Elem()) 128 } 129 case reflect.Struct: 130 return e.newStructTypeEncoder(t) 131 case reflect.Array: 132 fallthrough 133 case reflect.Slice: 134 return e.newArrayTypeEncoder(t) 135 case reflect.Map: 136 return e.newMapEncoder(t) 137 case reflect.Interface: 138 return e.newInterfaceEncoder() 139 default: 140 return e.newPrimitiveTypeEncoder(t) 141 } 142 } 143 144 func (e *encoder) newPrimitiveTypeEncoder(t reflect.Type) encoderFunc { 145 switch t.Kind() { 146 // Note that we could use `gjson` to encode these types but it would complicate our 147 // code more and this current code shouldn't cause any issues 148 case reflect.String: 149 return func(v reflect.Value) ([]byte, error) { 150 return json.Marshal(v.Interface()) 151 } 152 case reflect.Bool: 153 return func(v reflect.Value) ([]byte, error) { 154 if v.Bool() { 155 return []byte("true"), nil 156 } 157 return []byte("false"), nil 158 } 159 case reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64: 160 return func(v reflect.Value) ([]byte, error) { 161 return []byte(strconv.FormatInt(v.Int(), 10)), nil 162 } 163 case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64: 164 return func(v reflect.Value) ([]byte, error) { 165 return []byte(strconv.FormatUint(v.Uint(), 10)), nil 166 } 167 case reflect.Float32: 168 return func(v reflect.Value) ([]byte, error) { 169 return []byte(strconv.FormatFloat(v.Float(), 'f', -1, 32)), nil 170 } 171 case reflect.Float64: 172 return func(v reflect.Value) ([]byte, error) { 173 return []byte(strconv.FormatFloat(v.Float(), 'f', -1, 64)), nil 174 } 175 default: 176 return func(v reflect.Value) ([]byte, error) { 177 return nil, fmt.Errorf("unknown type received at primitive encoder: %s", t.String()) 178 } 179 } 180 } 181 182 func (e *encoder) newArrayTypeEncoder(t reflect.Type) encoderFunc { 183 itemEncoder := e.typeEncoder(t.Elem()) 184 185 return func(value reflect.Value) ([]byte, error) { 186 json := []byte("[]") 187 for i := 0; i < value.Len(); i++ { 188 var value, err = itemEncoder(value.Index(i)) 189 if err != nil { 190 return nil, err 191 } 192 if value == nil { 193 // Assume that empty items should be inserted as `null` so that the output array 194 // will be the same length as the input array 195 value = []byte("null") 196 } 197 198 json, err = sjson.SetRawBytes(json, "-1", value) 199 if err != nil { 200 return nil, err 201 } 202 } 203 204 return json, nil 205 } 206 } 207 208 func (e *encoder) newStructTypeEncoder(t reflect.Type) encoderFunc { 209 encoderFields := []encoderField{} 210 extraEncoder := (*encoderField)(nil) 211 212 // This helper allows us to recursively collect field encoders into a flat 213 // array. The parameter `index` keeps track of the access patterns necessary 214 // to get to some field. 215 var collectEncoderFields func(r reflect.Type, index []int) 216 collectEncoderFields = func(r reflect.Type, index []int) { 217 for i := 0; i < r.NumField(); i++ { 218 idx := append(index, i) 219 field := t.FieldByIndex(idx) 220 if !field.IsExported() { 221 continue 222 } 223 // If this is an embedded struct, traverse one level deeper to extract 224 // the field and get their encoders as well. 225 if field.Anonymous { 226 collectEncoderFields(field.Type, idx) 227 continue 228 } 229 // If json tag is not present, then we skip, which is intentionally 230 // different behavior from the stdlib. 231 ptag, ok := parseJSONStructTag(field) 232 if !ok { 233 continue 234 } 235 // We only want to support unexported field if they're tagged with 236 // `extras` because that field shouldn't be part of the public API. We 237 // also want to only keep the top level extras 238 if ptag.extras && len(index) == 0 { 239 extraEncoder = &encoderField{ptag, e.typeEncoder(field.Type.Elem()), idx} 240 continue 241 } 242 if ptag.name == "-" { 243 continue 244 } 245 246 dateFormat, ok := parseFormatStructTag(field) 247 oldFormat := e.dateFormat 248 if ok { 249 switch dateFormat { 250 case "date-time": 251 e.dateFormat = time.RFC3339 252 case "date": 253 e.dateFormat = "2006-01-02" 254 } 255 } 256 encoderFields = append(encoderFields, encoderField{ptag, e.typeEncoder(field.Type), idx}) 257 e.dateFormat = oldFormat 258 } 259 } 260 collectEncoderFields(t, []int{}) 261 262 // Ensure deterministic output by sorting by lexicographic order 263 sort.Slice(encoderFields, func(i, j int) bool { 264 return encoderFields[i].tag.name < encoderFields[j].tag.name 265 }) 266 267 return func(value reflect.Value) (json []byte, err error) { 268 json = []byte("{}") 269 270 for _, ef := range encoderFields { 271 field := value.FieldByIndex(ef.idx) 272 encoded, err := ef.fn(field) 273 if err != nil { 274 return nil, err 275 } 276 if ef.tag.defaultValue != nil && (!field.IsValid() || field.IsZero()) { 277 encoded, err = shimjson.Marshal(ef.tag.defaultValue) 278 if err != nil { 279 return nil, err 280 } 281 } 282 if encoded == nil { 283 continue 284 } 285 json, err = sjson.SetRawBytes(json, EscapeSJSONKey(ef.tag.name), encoded) 286 if err != nil { 287 return nil, err 288 } 289 } 290 291 if extraEncoder != nil { 292 json, err = e.encodeMapEntries(json, value.FieldByIndex(extraEncoder.idx)) 293 if err != nil { 294 return nil, err 295 } 296 } 297 return json, err 298 } 299 } 300 301 func (e *encoder) newTimeTypeEncoder() encoderFunc { 302 format := e.dateFormat 303 return func(value reflect.Value) (json []byte, err error) { 304 return []byte(`"` + value.Convert(reflect.TypeOf(time.Time{})).Interface().(time.Time).Format(format) + `"`), nil 305 } 306 } 307 308 func (e encoder) newInterfaceEncoder() encoderFunc { 309 return func(value reflect.Value) ([]byte, error) { 310 value = value.Elem() 311 if !value.IsValid() { 312 return nil, nil 313 } 314 return e.typeEncoder(value.Type())(value) 315 } 316 } 317 318 // Given a []byte of json (may either be an empty object or an object that already contains entries) 319 // encode all of the entries in the map to the json byte array. 320 func (e *encoder) encodeMapEntries(json []byte, v reflect.Value) ([]byte, error) { 321 type mapPair struct { 322 key []byte 323 value reflect.Value 324 } 325 326 pairs := []mapPair{} 327 keyEncoder := e.typeEncoder(v.Type().Key()) 328 329 iter := v.MapRange() 330 for iter.Next() { 331 var encodedKeyString string 332 if iter.Key().Type().Kind() == reflect.String { 333 encodedKeyString = iter.Key().String() 334 } else { 335 var err error 336 encodedKeyBytes, err := keyEncoder(iter.Key()) 337 if err != nil { 338 return nil, err 339 } 340 encodedKeyString = string(encodedKeyBytes) 341 } 342 encodedKey := []byte(encodedKeyString) 343 pairs = append(pairs, mapPair{key: encodedKey, value: iter.Value()}) 344 } 345 346 // Ensure deterministic output 347 sort.Slice(pairs, func(i, j int) bool { 348 return bytes.Compare(pairs[i].key, pairs[j].key) < 0 349 }) 350 351 elementEncoder := e.typeEncoder(v.Type().Elem()) 352 for _, p := range pairs { 353 encodedValue, err := elementEncoder(p.value) 354 if err != nil { 355 return nil, err 356 } 357 if len(encodedValue) == 0 { 358 continue 359 } 360 json, err = sjson.SetRawBytes(json, EscapeSJSONKey(string(p.key)), encodedValue) 361 if err != nil { 362 return nil, err 363 } 364 } 365 366 return json, nil 367 } 368 369 func (e *encoder) newMapEncoder(_ reflect.Type) encoderFunc { 370 return func(value reflect.Value) ([]byte, error) { 371 json := []byte("{}") 372 var err error 373 json, err = e.encodeMapEntries(json, value) 374 if err != nil { 375 return nil, err 376 } 377 return json, nil 378 } 379 }