github.com/anthropics/anthropic-sdk-go@v1.70.1/internal/apijson/decoder.go (about)

     1  // The deserialization algorithm from apijson may be subject to improvements
     2  // between minor versions, particularly with respect to calling [json.Unmarshal]
     3  // into param unions.
     4  
     5  package apijson
     6  
     7  import (
     8  	"encoding/json"
     9  	"fmt"
    10  	"reflect"
    11  	"strconv"
    12  	"sync"
    13  	"time"
    14  	"unsafe"
    15  
    16  	"github.com/anthropics/anthropic-sdk-go/packages/param"
    17  
    18  	"github.com/tidwall/gjson"
    19  )
    20  
    21  // decoders is a synchronized map with roughly the following type:
    22  // map[reflect.Type]decoderFunc
    23  var decoders sync.Map
    24  
    25  // Unmarshal is similar to [encoding/json.Unmarshal] and parses the JSON-encoded
    26  // data and stores it in the given pointer.
    27  func Unmarshal(raw []byte, to any) error {
    28  	d := &decoderBuilder{dateFormat: time.RFC3339}
    29  	return d.unmarshal(raw, to)
    30  }
    31  
    32  // UnmarshalRoot is like Unmarshal, but doesn't try to call MarshalJSON on the
    33  // root element. Useful if a struct's UnmarshalJSON is overrode to use the
    34  // behavior of this encoder versus the standard library.
    35  func UnmarshalRoot(raw []byte, to any) error {
    36  	d := &decoderBuilder{dateFormat: time.RFC3339, root: true}
    37  	return d.unmarshal(raw, to)
    38  }
    39  
    40  // decoderBuilder contains the 'compile-time' state of the decoder.
    41  type decoderBuilder struct {
    42  	// Whether or not this is the first element and called by [UnmarshalRoot], see
    43  	// the documentation there to see why this is necessary.
    44  	root bool
    45  	// The dateFormat (a format string for [time.Format]) which is chosen by the
    46  	// last struct tag that was seen.
    47  	dateFormat string
    48  }
    49  
    50  // decoderState contains the 'run-time' state of the decoder.
    51  type decoderState struct {
    52  	strict    bool
    53  	exactness exactness
    54  	validator *validationEntry
    55  }
    56  
    57  type decoderFunc func(node gjson.Result, value reflect.Value, state *decoderState) error
    58  
    59  type decoderField struct {
    60  	tag    parsedStructTag
    61  	fn     decoderFunc
    62  	idx    []int
    63  	goname string
    64  }
    65  
    66  type decoderEntry struct {
    67  	typ        reflect.Type
    68  	dateFormat string
    69  	root       bool
    70  }
    71  
    72  func (d *decoderBuilder) unmarshal(raw []byte, to any) error {
    73  	value := reflect.ValueOf(to).Elem()
    74  	result := gjson.ParseBytes(raw)
    75  	if !value.IsValid() {
    76  		return fmt.Errorf("apijson: cannot unmarshal into invalid value")
    77  	}
    78  	return d.typeDecoder(value.Type())(result, value, &decoderState{})
    79  }
    80  
    81  // unmarshalWithExactness is used for internal testing purposes.
    82  func (d *decoderBuilder) unmarshalWithExactness(raw []byte, to any) (exactness, error) {
    83  	value := reflect.ValueOf(to).Elem()
    84  	result := gjson.ParseBytes(raw)
    85  	if !value.IsValid() {
    86  		return exactness{}, fmt.Errorf("apijson: cannot marshal into invalid value")
    87  	}
    88  	var state decoderState
    89  	err := d.typeDecoder(value.Type())(result, value, &state)
    90  	return state.exactness, err
    91  }
    92  
    93  func (d *decoderBuilder) typeDecoder(t reflect.Type) decoderFunc {
    94  	entry := decoderEntry{
    95  		typ:        t,
    96  		dateFormat: d.dateFormat,
    97  		root:       d.root,
    98  	}
    99  
   100  	if fi, ok := decoders.Load(entry); ok {
   101  		return fi.(decoderFunc)
   102  	}
   103  
   104  	// To deal with recursive types, populate the map with an
   105  	// indirect func before we build it. This type waits on the
   106  	// real func (f) to be ready and then calls it. This indirect
   107  	// func is only used for recursive types.
   108  	var (
   109  		wg sync.WaitGroup
   110  		f  decoderFunc
   111  	)
   112  	wg.Add(1)
   113  	fi, loaded := decoders.LoadOrStore(entry, decoderFunc(func(node gjson.Result, v reflect.Value, state *decoderState) error {
   114  		wg.Wait()
   115  		return f(node, v, state)
   116  	}))
   117  	if loaded {
   118  		return fi.(decoderFunc)
   119  	}
   120  
   121  	// Compute the real decoder and replace the indirect func with it.
   122  	f = d.newTypeDecoder(t)
   123  	wg.Done()
   124  	decoders.Store(entry, f)
   125  	return f
   126  }
   127  
   128  // validatedTypeDecoder wraps the type decoder with a validator. This is helpful
   129  // for ensuring that enum fields are correct.
   130  func (d *decoderBuilder) validatedTypeDecoder(t reflect.Type, entry *validationEntry) decoderFunc {
   131  	dec := d.typeDecoder(t)
   132  	if entry == nil {
   133  		return dec
   134  	}
   135  
   136  	// Thread the current validation entry through the decoder,
   137  	// but clean up in time for the next field.
   138  	return func(node gjson.Result, v reflect.Value, state *decoderState) error {
   139  		state.validator = entry
   140  		err := dec(node, v, state)
   141  		state.validator = nil
   142  		return err
   143  	}
   144  }
   145  
   146  func indirectUnmarshalerDecoder(n gjson.Result, v reflect.Value, state *decoderState) error {
   147  	return v.Addr().Interface().(json.Unmarshaler).UnmarshalJSON([]byte(n.Raw))
   148  }
   149  
   150  func customUnmarshalerDecoder(n gjson.Result, v reflect.Value, state *decoderState) error {
   151  	if v.Kind() == reflect.Pointer && v.CanSet() {
   152  		v.Set(reflect.New(v.Type().Elem()))
   153  	}
   154  	if u, ok := v.Interface().(CustomUnmarshaler); ok {
   155  		return u.UnmarshalAPIJSON([]byte(n.Raw))
   156  	}
   157  	return v.Addr().Interface().(CustomUnmarshaler).UnmarshalAPIJSON([]byte(n.Raw))
   158  }
   159  
   160  func unmarshalerDecoder(n gjson.Result, v reflect.Value, state *decoderState) error {
   161  	if v.Kind() == reflect.Pointer && v.CanSet() {
   162  		v.Set(reflect.New(v.Type().Elem()))
   163  	}
   164  	return v.Interface().(json.Unmarshaler).UnmarshalJSON([]byte(n.Raw))
   165  }
   166  
   167  func (d *decoderBuilder) newTypeDecoder(t reflect.Type) decoderFunc {
   168  	// Check for custom decoders first
   169  	if customDecoder, ok := customDecoderRegistry[t]; ok {
   170  		// Create the default decoder for this type (without the custom decoder)
   171  		defaultDecoder := d.newDefaultTypeDecoder(t)
   172  		return func(node gjson.Result, value reflect.Value, state *decoderState) error {
   173  			// Provide a wrapper that removes the state parameter for the custom decoder
   174  			defaultWrapper := func(node gjson.Result, value reflect.Value) error {
   175  				return defaultDecoder(node, value, state)
   176  			}
   177  			return customDecoder(node, value, defaultWrapper)
   178  		}
   179  	}
   180  
   181  	return d.newDefaultTypeDecoder(t)
   182  }
   183  
   184  func (d *decoderBuilder) newDefaultTypeDecoder(t reflect.Type) decoderFunc {
   185  	if t.ConvertibleTo(reflect.TypeOf(time.Time{})) {
   186  		return d.newTimeTypeDecoder(t)
   187  	}
   188  
   189  	if t.Implements(reflect.TypeOf((*param.Optional)(nil)).Elem()) {
   190  		return d.newOptTypeDecoder(t)
   191  	}
   192  
   193  	if !d.root && implementsCustomUnmarshaler(t) {
   194  		return customUnmarshalerDecoder
   195  	}
   196  
   197  	// apijson-native types are decoded directly; see [isApijsonNative].
   198  	if !d.root && !isApijsonNative(t) && t.Implements(reflect.TypeOf((*json.Unmarshaler)(nil)).Elem()) {
   199  		return unmarshalerDecoder
   200  	}
   201  	if !d.root && !isApijsonNative(t) && reflect.PointerTo(t).Implements(reflect.TypeOf((*json.Unmarshaler)(nil)).Elem()) {
   202  		if _, ok := unionVariants[t]; !ok {
   203  			return indirectUnmarshalerDecoder
   204  		}
   205  	}
   206  	d.root = false
   207  
   208  	if _, ok := unionRegistry[t]; ok {
   209  		if isStructUnion(t) {
   210  			return d.newStructUnionDecoder(t)
   211  		}
   212  		return d.newUnionDecoder(t)
   213  	}
   214  
   215  	switch t.Kind() {
   216  	case reflect.Pointer:
   217  		inner := t.Elem()
   218  		innerDecoder := d.typeDecoder(inner)
   219  
   220  		return func(n gjson.Result, v reflect.Value, state *decoderState) error {
   221  			if !v.IsValid() {
   222  				return fmt.Errorf("apijson: unexpected invalid reflection value %+#v", v)
   223  			}
   224  
   225  			newValue := reflect.New(inner).Elem()
   226  			err := innerDecoder(n, newValue, state)
   227  			if err != nil {
   228  				return err
   229  			}
   230  
   231  			v.Set(newValue.Addr())
   232  			return nil
   233  		}
   234  	case reflect.Struct:
   235  		if isStructUnion(t) {
   236  			return d.newStructUnionDecoder(t)
   237  		}
   238  		return d.newStructTypeDecoder(t)
   239  	case reflect.Array:
   240  		fallthrough
   241  	case reflect.Slice:
   242  		return d.newArrayTypeDecoder(t)
   243  	case reflect.Map:
   244  		return d.newMapDecoder(t)
   245  	case reflect.Interface:
   246  		return func(node gjson.Result, value reflect.Value, state *decoderState) error {
   247  			if !value.IsValid() {
   248  				return fmt.Errorf("apijson: unexpected invalid value %+#v", value)
   249  			}
   250  			if node.Value() != nil && value.CanSet() {
   251  				value.Set(reflect.ValueOf(node.Value()))
   252  			}
   253  			return nil
   254  		}
   255  	default:
   256  		return d.newPrimitiveTypeDecoder(t)
   257  	}
   258  }
   259  
   260  func (d *decoderBuilder) newMapDecoder(t reflect.Type) decoderFunc {
   261  	keyType := t.Key()
   262  	itemType := t.Elem()
   263  	itemDecoder := d.typeDecoder(itemType)
   264  
   265  	return func(node gjson.Result, value reflect.Value, state *decoderState) (err error) {
   266  		mapValue := reflect.MakeMapWithSize(t, len(node.Map()))
   267  
   268  		node.ForEach(func(key, value gjson.Result) bool {
   269  			// It's fine for us to just use `ValueOf` here because the key types will
   270  			// always be primitive types so we don't need to decode it using the standard pattern
   271  			keyValue := reflect.ValueOf(key.Value())
   272  			if !keyValue.IsValid() {
   273  				if err == nil {
   274  					err = fmt.Errorf("apijson: received invalid key type %v", keyValue.String())
   275  				}
   276  				return false
   277  			}
   278  			if keyValue.Type() != keyType {
   279  				if err == nil {
   280  					err = fmt.Errorf("apijson: expected key type %v but got %v", keyType, keyValue.Type())
   281  				}
   282  				return false
   283  			}
   284  
   285  			itemValue := reflect.New(itemType).Elem()
   286  			itemerr := itemDecoder(value, itemValue, state)
   287  			if itemerr != nil {
   288  				if err == nil {
   289  					err = itemerr
   290  				}
   291  				return false
   292  			}
   293  
   294  			mapValue.SetMapIndex(keyValue, itemValue)
   295  			return true
   296  		})
   297  
   298  		if err != nil {
   299  			return err
   300  		}
   301  		value.Set(mapValue)
   302  		return nil
   303  	}
   304  }
   305  
   306  func (d *decoderBuilder) newArrayTypeDecoder(t reflect.Type) decoderFunc {
   307  	itemDecoder := d.typeDecoder(t.Elem())
   308  
   309  	return func(node gjson.Result, value reflect.Value, state *decoderState) (err error) {
   310  		if !node.IsArray() {
   311  			return fmt.Errorf("apijson: could not deserialize to an array")
   312  		}
   313  
   314  		arrayNode := node.Array()
   315  
   316  		arrayValue := reflect.MakeSlice(reflect.SliceOf(t.Elem()), len(arrayNode), len(arrayNode))
   317  		for i, itemNode := range arrayNode {
   318  			err = itemDecoder(itemNode, arrayValue.Index(i), state)
   319  			if err != nil {
   320  				return err
   321  			}
   322  		}
   323  
   324  		value.Set(arrayValue)
   325  		return nil
   326  	}
   327  }
   328  
   329  func (d *decoderBuilder) newStructTypeDecoder(t reflect.Type) decoderFunc {
   330  	// map of json field name to struct field decoders
   331  	decoderFields := map[string]decoderField{}
   332  	anonymousDecoders := []decoderField{}
   333  	extraDecoder := (*decoderField)(nil)
   334  	var inlineDecoders []decoderField
   335  
   336  	// Missing api:"required" fields lower a param variant's rank.
   337  	isParam := isParamStruct(t)
   338  	requiredCount := 0
   339  
   340  	validationEntries := validationRegistry[t]
   341  
   342  	for i := 0; i < t.NumField(); i++ {
   343  		idx := []int{i}
   344  		field := t.FieldByIndex(idx)
   345  		if !field.IsExported() {
   346  			continue
   347  		}
   348  
   349  		var validator *validationEntry
   350  		for _, entry := range validationEntries {
   351  			if entry.field.Offset == field.Offset {
   352  				validator = &entry
   353  				break
   354  			}
   355  		}
   356  
   357  		// If this is an embedded struct, traverse one level deeper to extract
   358  		// the fields and get their encoders as well.
   359  		if field.Anonymous {
   360  			anonymousDecoders = append(anonymousDecoders, decoderField{
   361  				fn:  d.typeDecoder(field.Type),
   362  				idx: idx[:],
   363  			})
   364  			continue
   365  		}
   366  		// If json tag is not present, then we skip, which is intentionally
   367  		// different behavior from the stdlib.
   368  		ptag, ok := parseJSONStructTag(field)
   369  		if !ok {
   370  			continue
   371  		}
   372  		// We only want to support unexported fields if they're tagged with
   373  		// `extras` because that field shouldn't be part of the public API.
   374  		if ptag.extras {
   375  			extraDecoder = &decoderField{ptag, d.typeDecoder(field.Type.Elem()), idx, field.Name}
   376  			continue
   377  		}
   378  		if ptag.inline {
   379  			df := decoderField{ptag, d.typeDecoder(field.Type), idx, field.Name}
   380  			inlineDecoders = append(inlineDecoders, df)
   381  			continue
   382  		}
   383  		if ptag.metadata {
   384  			continue
   385  		}
   386  
   387  		oldFormat := d.dateFormat
   388  		dateFormat, ok := parseFormatStructTag(field)
   389  		if ok {
   390  			switch dateFormat {
   391  			case "date-time":
   392  				d.dateFormat = time.RFC3339
   393  			case "date":
   394  				d.dateFormat = "2006-01-02"
   395  			}
   396  		}
   397  
   398  		fn := d.validatedTypeDecoder(field.Type, validator)
   399  		if def, ok := ptag.defaultValue.(string); ok && field.Type.Kind() == reflect.String {
   400  			fn = constantFieldDecoder(fn, def)
   401  		}
   402  		decoderFields[ptag.name] = decoderField{ptag, fn, idx, field.Name}
   403  		if isParam && ptag.required {
   404  			requiredCount++
   405  		}
   406  
   407  		d.dateFormat = oldFormat
   408  	}
   409  
   410  	return func(node gjson.Result, value reflect.Value, state *decoderState) (err error) {
   411  		if field := value.FieldByName("JSON"); field.IsValid() {
   412  			if raw := field.FieldByName("raw"); raw.IsValid() {
   413  				setUnexportedField(raw, node.Raw)
   414  			}
   415  		}
   416  
   417  		for _, decoder := range anonymousDecoders {
   418  			// ignore errors
   419  			_ = decoder.fn(node, value.FieldByIndex(decoder.idx), state)
   420  		}
   421  
   422  		for _, inlineDecoder := range inlineDecoders {
   423  			var meta Field
   424  			dest := value.FieldByIndex(inlineDecoder.idx)
   425  			isValid := false
   426  			if dest.IsValid() && node.Type != gjson.Null {
   427  				inlineState := decoderState{exactness: state.exactness, strict: true}
   428  				err = inlineDecoder.fn(node, dest, &inlineState)
   429  				if err == nil {
   430  					isValid = true
   431  				}
   432  			}
   433  
   434  			if node.Type == gjson.Null {
   435  				meta = Field{
   436  					raw:    node.Raw,
   437  					status: null,
   438  				}
   439  			} else if !isValid {
   440  				// If an inline decoder fails, unset the field and move on.
   441  				if dest.IsValid() {
   442  					dest.SetZero()
   443  				}
   444  				continue
   445  			} else if isValid {
   446  				meta = Field{
   447  					raw:    node.Raw,
   448  					status: valid,
   449  				}
   450  			}
   451  			setMetadataSubField(value, inlineDecoder.idx, inlineDecoder.goname, meta)
   452  		}
   453  
   454  		typedExtraType := reflect.Type(nil)
   455  		typedExtraFields := reflect.Value{}
   456  		if extraDecoder != nil {
   457  			typedExtraType = value.FieldByIndex(extraDecoder.idx).Type()
   458  			typedExtraFields = reflect.MakeMap(typedExtraType)
   459  		}
   460  		untypedExtraFields := map[string]Field{}
   461  		seenRequired := 0
   462  
   463  		for fieldName, itemNode := range node.Map() {
   464  			df, explicit := decoderFields[fieldName]
   465  			var (
   466  				dest reflect.Value
   467  				fn   decoderFunc
   468  				meta Field
   469  			)
   470  			if explicit {
   471  				fn = df.fn
   472  				dest = value.FieldByIndex(df.idx)
   473  			}
   474  			if !explicit && extraDecoder != nil {
   475  				dest = reflect.New(typedExtraType.Elem()).Elem()
   476  				fn = extraDecoder.fn
   477  			}
   478  
   479  			// Handle null [param.Opt]
   480  			if itemNode.Type == gjson.Null && dest.IsValid() && dest.Type().Implements(reflect.TypeOf((*param.Optional)(nil)).Elem()) {
   481  				_ = dest.Addr().Interface().(json.Unmarshaler).UnmarshalJSON([]byte(itemNode.Raw))
   482  				if explicit && df.tag.required {
   483  					seenRequired++
   484  				}
   485  				continue
   486  			}
   487  
   488  			isValid := false
   489  			if dest.IsValid() && itemNode.Type != gjson.Null {
   490  				err = fn(itemNode, dest, state)
   491  				if err == nil {
   492  					isValid = true
   493  				} else {
   494  					state.exactness.noteFieldError()
   495  				}
   496  			}
   497  			if explicit && df.tag.required && isValid {
   498  				seenRequired++
   499  			}
   500  
   501  			if itemNode.Type == gjson.Null {
   502  				meta = Field{
   503  					raw:    itemNode.Raw,
   504  					status: null,
   505  				}
   506  			} else if !isValid {
   507  				meta = Field{
   508  					raw:    itemNode.Raw,
   509  					status: invalid,
   510  				}
   511  			} else if isValid {
   512  				meta = Field{
   513  					raw:    itemNode.Raw,
   514  					status: valid,
   515  				}
   516  			}
   517  
   518  			if explicit {
   519  				setMetadataSubField(value, df.idx, df.goname, meta)
   520  			}
   521  			if !explicit {
   522  				untypedExtraFields[fieldName] = meta
   523  			}
   524  			if !explicit && extraDecoder != nil {
   525  				typedExtraFields.SetMapIndex(reflect.ValueOf(fieldName), dest)
   526  			}
   527  		}
   528  
   529  		if extraDecoder != nil && typedExtraFields.Len() > 0 {
   530  			value.FieldByIndex(extraDecoder.idx).Set(typedExtraFields)
   531  		}
   532  
   533  		if seenRequired < requiredCount {
   534  			state.exactness.noteRequiredMissing(requiredCount - seenRequired)
   535  		}
   536  
   537  		if len(untypedExtraFields) > 0 {
   538  			state.exactness.noteExtras()
   539  			setMetadataExtraFields(value, []int{-1}, "ExtraFields", untypedExtraFields)
   540  		}
   541  		return nil
   542  	}
   543  }
   544  
   545  func (d *decoderBuilder) newPrimitiveTypeDecoder(t reflect.Type) decoderFunc {
   546  	switch t.Kind() {
   547  	case reflect.String:
   548  		return func(n gjson.Result, v reflect.Value, state *decoderState) error {
   549  			v.SetString(n.String())
   550  			if guardStrict(state, n.Type != gjson.String) {
   551  				return fmt.Errorf("apijson: failed to parse string strictly")
   552  			}
   553  			// Everything that is not an object can be loosely stringified.
   554  			if n.Type == gjson.JSON {
   555  				return fmt.Errorf("apijson: failed to parse string")
   556  			}
   557  
   558  			state.validateString(v)
   559  
   560  			if guardUnknown(state, v) {
   561  				return fmt.Errorf("apijson: failed string enum validation")
   562  			}
   563  			return nil
   564  		}
   565  	case reflect.Bool:
   566  		return func(n gjson.Result, v reflect.Value, state *decoderState) error {
   567  			v.SetBool(n.Bool())
   568  			if guardStrict(state, n.Type != gjson.True && n.Type != gjson.False) {
   569  				return fmt.Errorf("apijson: failed to parse bool strictly")
   570  			}
   571  			// Numbers and strings that are either 'true' or 'false' can be loosely
   572  			// deserialized as bool.
   573  			if n.Type == gjson.String && (n.Raw != "true" && n.Raw != "false") || n.Type == gjson.JSON {
   574  				return fmt.Errorf("apijson: failed to parse bool")
   575  			}
   576  
   577  			state.validateBool(v)
   578  
   579  			if guardUnknown(state, v) {
   580  				return fmt.Errorf("apijson: failed bool enum validation")
   581  			}
   582  			return nil
   583  		}
   584  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   585  		return func(n gjson.Result, v reflect.Value, state *decoderState) error {
   586  			v.SetInt(n.Int())
   587  			if guardStrict(state, n.Type != gjson.Number || n.Num != float64(int(n.Num))) {
   588  				return fmt.Errorf("apijson: failed to parse int strictly")
   589  			}
   590  			// Numbers, booleans, and strings that maybe look like numbers can be
   591  			// loosely deserialized as numbers.
   592  			if n.Type == gjson.JSON || (n.Type == gjson.String && !canParseAsNumber(n.Str)) {
   593  				return fmt.Errorf("apijson: failed to parse int")
   594  			}
   595  
   596  			state.validateInt(v)
   597  
   598  			if guardUnknown(state, v) {
   599  				return fmt.Errorf("apijson: failed int enum validation")
   600  			}
   601  			return nil
   602  		}
   603  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
   604  		return func(n gjson.Result, v reflect.Value, state *decoderState) error {
   605  			v.SetUint(n.Uint())
   606  			if guardStrict(state, n.Type != gjson.Number || n.Num != float64(int(n.Num)) || n.Num < 0) {
   607  				return fmt.Errorf("apijson: failed to parse uint strictly")
   608  			}
   609  			// Numbers, booleans, and strings that maybe look like numbers can be
   610  			// loosely deserialized as uint.
   611  			if n.Type == gjson.JSON || (n.Type == gjson.String && !canParseAsNumber(n.Str)) {
   612  				return fmt.Errorf("apijson: failed to parse uint")
   613  			}
   614  			if guardUnknown(state, v) {
   615  				return fmt.Errorf("apijson: failed uint enum validation")
   616  			}
   617  			return nil
   618  		}
   619  	case reflect.Float32, reflect.Float64:
   620  		return func(n gjson.Result, v reflect.Value, state *decoderState) error {
   621  			v.SetFloat(n.Float())
   622  			if guardStrict(state, n.Type != gjson.Number) {
   623  				return fmt.Errorf("apijson: failed to parse float strictly")
   624  			}
   625  			// Numbers, booleans, and strings that maybe look like numbers can be
   626  			// loosely deserialized as floats.
   627  			if n.Type == gjson.JSON || (n.Type == gjson.String && !canParseAsNumber(n.Str)) {
   628  				return fmt.Errorf("apijson: failed to parse float")
   629  			}
   630  			if guardUnknown(state, v) {
   631  				return fmt.Errorf("apijson: failed float enum validation")
   632  			}
   633  			return nil
   634  		}
   635  	default:
   636  		return func(node gjson.Result, v reflect.Value, state *decoderState) error {
   637  			return fmt.Errorf("unknown type received at primitive decoder: %s", t.String())
   638  		}
   639  	}
   640  }
   641  
   642  func (d *decoderBuilder) newOptTypeDecoder(t reflect.Type) decoderFunc {
   643  	for t.Kind() == reflect.Pointer {
   644  		t = t.Elem()
   645  	}
   646  	valueField, _ := t.FieldByName("Value")
   647  	return func(n gjson.Result, v reflect.Value, state *decoderState) error {
   648  		state.validateOptKind(n, valueField.Type)
   649  		return v.Addr().Interface().(json.Unmarshaler).UnmarshalJSON([]byte(n.Raw))
   650  	}
   651  }
   652  
   653  func (d *decoderBuilder) newTimeTypeDecoder(t reflect.Type) decoderFunc {
   654  	format := d.dateFormat
   655  	return func(n gjson.Result, v reflect.Value, state *decoderState) error {
   656  		parsed, err := time.Parse(format, n.Str)
   657  		if err == nil {
   658  			v.Set(reflect.ValueOf(parsed).Convert(t))
   659  			return nil
   660  		}
   661  
   662  		if guardStrict(state, true) {
   663  			return err
   664  		}
   665  
   666  		layouts := []string{
   667  			"2006-01-02",
   668  			"2006-01-02T15:04:05Z07:00",
   669  			"2006-01-02T15:04:05Z0700",
   670  			"2006-01-02T15:04:05",
   671  			"2006-01-02 15:04:05Z07:00",
   672  			"2006-01-02 15:04:05Z0700",
   673  			"2006-01-02 15:04:05",
   674  		}
   675  
   676  		for _, layout := range layouts {
   677  			parsed, err := time.Parse(layout, n.Str)
   678  			if err == nil {
   679  				v.Set(reflect.ValueOf(parsed).Convert(t))
   680  				return nil
   681  			}
   682  		}
   683  
   684  		return fmt.Errorf("unable to leniently parse date-time string: %s", n.Str)
   685  	}
   686  }
   687  
   688  func setUnexportedField(field reflect.Value, value any) {
   689  	reflect.NewAt(field.Type(), unsafe.Pointer(field.UnsafeAddr())).Elem().Set(reflect.ValueOf(value))
   690  }
   691  
   692  func guardStrict(state *decoderState, cond bool) bool {
   693  	if !cond {
   694  		return false
   695  	}
   696  
   697  	if state.strict {
   698  		return true
   699  	}
   700  
   701  	state.exactness.noteCoercion()
   702  	return false
   703  }
   704  
   705  func canParseAsNumber(str string) bool {
   706  	_, err := strconv.ParseFloat(str, 64)
   707  	return err == nil
   708  }
   709  
   710  func guardUnknown(state *decoderState, v reflect.Value) bool {
   711  	if have, ok := v.Interface().(interface{ IsKnown() bool }); ok && !have.IsKnown() {
   712  		state.exactness.noteCoercion()
   713  	}
   714  	return false
   715  }
   716  
   717  // To feed union variant selection, record whether a constant field
   718  // matched its default.
   719  func constantFieldDecoder(inner decoderFunc, def string) decoderFunc {
   720  	return func(n gjson.Result, v reflect.Value, state *decoderState) error {
   721  		if err := inner(n, v, state); err != nil {
   722  			return err
   723  		}
   724  		if v.String() == def {
   725  			state.exactness.noteConstMatch()
   726  		} else {
   727  			state.exactness.noteConstMismatch()
   728  		}
   729  		return nil
   730  	}
   731  }