packages/param/encoder.go (106 lines of code) (raw):

package param import ( "encoding/json" "fmt" "reflect" "strings" "sync" "time" shimjson "github.com/anthropics/anthropic-sdk-go/internal/encoding/json" "github.com/tidwall/sjson" ) // This type will not be stable and shouldn't be relied upon type EncodedAsDate Opt[time.Time] func (m EncodedAsDate) MarshalJSON() ([]byte, error) { underlying := Opt[time.Time](m) bytes := underlying.MarshalJSONWithTimeLayout("2006-01-02") if len(bytes) > 0 { return bytes, nil } return underlying.MarshalJSON() } // This uses a shimmed 'encoding/json' from Go 1.24, to support the 'omitzero' tag func MarshalObject[T OverridableObject](f T, underlying any) ([]byte, error) { if f.IsNull() { return []byte("null"), nil } else if extras := f.GetExtraFields(); extras != nil { bytes, err := shimjson.Marshal(underlying) if err != nil { return nil, err } for k, v := range extras { bytes, err = sjson.SetBytes(bytes, k, v) if err != nil { return nil, err } } return bytes, nil } else if ovr, ok := f.IsOverridden(); ok { return shimjson.Marshal(ovr) } else { return shimjson.Marshal(underlying) } } // This uses a shimmed 'encoding/json' from Go 1.24, to support the 'omitzero' tag func MarshalUnion[T any](variants ...any) ([]byte, error) { nPresent := 0 presentIdx := -1 for i, variant := range variants { if !IsOmitted(variant) { nPresent++ presentIdx = i } } if nPresent == 0 || presentIdx == -1 { return []byte(`null`), nil } else if nPresent > 1 { return nil, &json.MarshalerError{ Type: typeFor[T](), Err: fmt.Errorf("expected union to have only one present variant, got %d", nPresent), } } return shimjson.Marshal(variants[presentIdx]) } // shimmed from Go 1.23 "reflect" package func typeFor[T any]() reflect.Type { var v T if t := reflect.TypeOf(v); t != nil { return t // optimize for T being a non-interface kind } return reflect.TypeOf((*T)(nil)).Elem() // only for an interface kind } var optStringType = typeFor[Opt[string]]() var optIntType = typeFor[Opt[int64]]() var optFloatType = typeFor[Opt[float64]]() var optBoolType = typeFor[Opt[bool]]() var OptionalPrimitiveTypes map[reflect.Type][]int // indexOfUnderlyingValueField must only be called at initialization time func indexOfUnderlyingValueField(t reflect.Type) []int { field, ok := t.FieldByName("Value") if !ok { panic("unreachable: initialization issue, underlying value field not found") } return field.Index } func init() { OptionalPrimitiveTypes = map[reflect.Type][]int{ optStringType: indexOfUnderlyingValueField(optStringType), optIntType: indexOfUnderlyingValueField(optIntType), optFloatType: indexOfUnderlyingValueField(optFloatType), optBoolType: indexOfUnderlyingValueField(optBoolType), } } var structFieldsCache sync.Map func structFields(t reflect.Type) (map[string][]int, error) { if cached, ok := structFieldsCache.Load(t); ok { return cached.(map[string][]int), nil } if t.Kind() != reflect.Struct { return nil, fmt.Errorf("resp: expected struct but got %v of kind %v", t.String(), t.Kind().String()) } structFields := map[string][]int{} for i := 0; i < t.NumField(); i++ { field := t.Field(i) name := strings.Split(field.Tag.Get("json"), ",")[0] if name == "" || name == "-" || field.Anonymous { continue } structFields[name] = field.Index } return structFields, nil }