Source file src/encoding/json/v2/arshal_methods.go

     1  // Copyright 2020 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build goexperiment.jsonv2
     6  
     7  package json
     8  
     9  import (
    10  	"encoding"
    11  	"errors"
    12  	"io"
    13  	"reflect"
    14  
    15  	"encoding/json/internal"
    16  	"encoding/json/internal/jsonflags"
    17  	"encoding/json/internal/jsonopts"
    18  	"encoding/json/internal/jsonwire"
    19  	"encoding/json/jsontext"
    20  )
    21  
    22  var errNonStringValue = errors.New("JSON value must be string type")
    23  
    24  // Interfaces for custom serialization.
    25  var (
    26  	jsonMarshalerType       = reflect.TypeFor[Marshaler]()
    27  	jsonMarshalerToType     = reflect.TypeFor[MarshalerTo]()
    28  	jsonUnmarshalerType     = reflect.TypeFor[Unmarshaler]()
    29  	jsonUnmarshalerFromType = reflect.TypeFor[UnmarshalerFrom]()
    30  	textAppenderType        = reflect.TypeFor[encoding.TextAppender]()
    31  	textMarshalerType       = reflect.TypeFor[encoding.TextMarshaler]()
    32  	textUnmarshalerType     = reflect.TypeFor[encoding.TextUnmarshaler]()
    33  
    34  	allMarshalerTypes   = []reflect.Type{jsonMarshalerToType, jsonMarshalerType, textAppenderType, textMarshalerType}
    35  	allUnmarshalerTypes = []reflect.Type{jsonUnmarshalerFromType, jsonUnmarshalerType, textUnmarshalerType}
    36  	allMethodTypes      = append(allMarshalerTypes, allUnmarshalerTypes...)
    37  )
    38  
    39  // Marshaler is implemented by types that can marshal themselves.
    40  // It is recommended that types implement [MarshalerTo] unless the implementation
    41  // is trying to avoid directly depending on the "jsontext" package.
    42  //
    43  // Implementations should return a buffer that is safe
    44  // for the caller to retain and potentially mutate.
    45  //
    46  // Implementations must not return [errors.ErrUnsupported].
    47  //
    48  // If the returned error is a [SemanticError], then unpopulated fields
    49  // of the error may be populated by [json] with additional context.
    50  // Errors of other types are wrapped within a [SemanticError].
    51  //
    52  // Implementations should assume [Deterministic] is true and return
    53  // deterministic output.
    54  type Marshaler interface {
    55  	MarshalJSON() ([]byte, error)
    56  }
    57  
    58  // MarshalerTo is implemented by types that can marshal themselves.
    59  // It is recommended that types implement MarshalerTo instead of [Marshaler]
    60  // since it is both more performant and more flexible.
    61  // If a type implements both Marshaler and MarshalerTo,
    62  // then MarshalerTo takes precedence. In such a case, both implementations
    63  // should aim to have equivalent behavior for the default marshal options.
    64  //
    65  // The implementation must write only one JSON value to the Encoder.
    66  // Alternatively, it may return [errors.ErrUnsupported] without mutating
    67  // the Encoder. The "json" package calling the method will
    68  // use the next available JSON representation for the receiver type,
    69  // as described in [Marshal].
    70  // Implementations must not retain the pointer to [jsontext.Encoder].
    71  //
    72  // If the returned error is a [SemanticError], then unpopulated fields
    73  // of the error may be populated by [json] with additional context.
    74  // Errors of other types are wrapped within a [SemanticError],
    75  // except for IO errors.
    76  //
    77  // The MarshalJSONTo method should not be called directly as it may
    78  // return sentinel errors that need special handling.
    79  // Users should instead call [MarshalEncode], which handles such cases.
    80  //
    81  // Implementations should inspect the marshal options from
    82  // [jsontext.Encoder.Options] and adjust behavior to respect the options as
    83  // necessary.
    84  //
    85  // The following options may be relevant to MarshalerTo implementations:
    86  //
    87  //   - [Deterministic]: if the implementation may produce non-deterministic output
    88  //   - [StringifyNumbers]: if the type is represented as a JSON number
    89  //
    90  // Several options, such as [FormatNilSliceAsNull], apply only to native Go
    91  // types. Thus, these options are typically not directly relevant to
    92  // MarshalerTo implementations. However, types representing a composite type
    93  // should marshal contained types using [MarshalEncode] to ensure these options
    94  // apply to the contained types. Similarly, [WithMarshalers] may influence
    95  // marshaling of any contained type within a composite type.
    96  //
    97  // All other options are automatically handled outside of the MarshalerTo
    98  // implementation, and thus are not relevant to implementations.
    99  type MarshalerTo interface {
   100  	MarshalJSONTo(*jsontext.Encoder) error
   101  }
   102  
   103  // Unmarshaler is implemented by types that can unmarshal themselves.
   104  // It is recommended that types implement [UnmarshalerFrom] unless the implementation
   105  // is trying to avoid a direct dependency on the "jsontext" package.
   106  //
   107  // The input can be assumed to be a valid encoding of a JSON value
   108  // if called from unmarshal functionality in this package.
   109  // It is recommended that UnmarshalJSON implement merge semantics
   110  // when unmarshaling into a pre-populated value, as described in [Unmarshal].
   111  //
   112  // Implementations must not retain or mutate the input []byte.
   113  //
   114  // Implementations must not return [errors.ErrUnsupported].
   115  //
   116  // If the returned error is a [SemanticError], then unpopulated fields
   117  // of the error may be populated by [json] with additional context.
   118  // Errors of other types are wrapped within a [SemanticError].
   119  type Unmarshaler interface {
   120  	UnmarshalJSON([]byte) error
   121  }
   122  
   123  // UnmarshalerFrom is implemented by types that can unmarshal themselves.
   124  // It is recommended that types implement UnmarshalerFrom instead of [Unmarshaler]
   125  // since this is both more performant and more flexible.
   126  // If a type implements both Unmarshaler and UnmarshalerFrom,
   127  // then UnmarshalerFrom takes precedence. In such a case, both implementations
   128  // should aim to have equivalent behavior for the default unmarshal options.
   129  //
   130  // The implementation must read only one JSON value from the Decoder.
   131  // It is recommended that UnmarshalJSONFrom implement merge semantics when
   132  // unmarshaling into a pre-populated value, as described in [Unmarshal].
   133  // Alternatively, it may return [errors.ErrUnsupported] without mutating
   134  // the Decoder. The "json" package calling the method will
   135  // use the next available JSON representation for the receiver type.
   136  // Implementations must not retain the pointer to [jsontext.Decoder].
   137  //
   138  // If the returned error is a [SemanticError], then unpopulated fields
   139  // of the error may be populated by [json] with additional context.
   140  // Errors of other types are wrapped within a [SemanticError],
   141  // except for [jsontext.SyntacticError]s and IO errors.
   142  //
   143  // The UnmarshalJSONFrom method should not be called directly as it may
   144  // return sentinel errors that need special handling.
   145  // Users should instead call [UnmarshalDecode], which handles such cases.
   146  //
   147  // Implementations should inspect the unmarshal options from
   148  // [jsontext.Decoder.Options] and adjust behavior to respect the options as
   149  // necessary.
   150  //
   151  // The following options may be relevant to UnmarshalerFrom implementations:
   152  //
   153  //   - [StringifyNumbers]: if the type is represented as a JSON number
   154  //
   155  // Several options, such as [FormatNilSliceAsNull], apply only to native Go
   156  // types. Thus, these options are typically not directly relevant to
   157  // UnmarshalerFrom implementations. However, types representing a composite
   158  // type should unmarshal contained types using [UnmarshalDecode] to ensure
   159  // these options apply to the contained types. Similarly, [WithUnmarshalers]
   160  // may influence unmarshaling of any contained type within a composite type.
   161  //
   162  // All other options are automatically handled outside of the UnmarshalerFrom
   163  // implementation, and thus are not relevant to implementations.
   164  type UnmarshalerFrom interface {
   165  	UnmarshalJSONFrom(*jsontext.Decoder) error
   166  }
   167  
   168  func makeMethodMarshaler(fncs *marshaler, t reflect.Type) *marshaler {
   169  	// Avoid injecting method marshaler on the pointer or interface version
   170  	// to avoid ever calling the method on a nil pointer or interface receiver.
   171  	// Let it be injected on the value receiver (which is always addressable).
   172  	if t.Kind() == reflect.Pointer || t.Kind() == reflect.Interface {
   173  		return fncs
   174  	}
   175  
   176  	if needAddr, ok := implements(t, textMarshalerType); ok {
   177  		fncs.nonDefault = true
   178  		prevMarshal := fncs.fnc
   179  		fncs.fnc = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
   180  			if mo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
   181  				((needAddr && va.forcedAddr) ||
   182  					(va.forcedAddr && export.Encoder(enc).Tokens.Last.NeedObjectName() && t.Kind() == reflect.String)) {
   183  				// Do not call MarshalText on unaddressable values and map keys of string kind.
   184  				// A map key of pointer kind is dereferenced before reaching here,
   185  				// in which case va.forcedAddr is false and MarshalText is still called.
   186  				return prevMarshal(enc, va, mo)
   187  			}
   188  			marshaler, _ := reflect.TypeAssert[encoding.TextMarshaler](va.Addr())
   189  			if err := export.Encoder(enc).AppendRaw('"', false, func(b []byte) ([]byte, error) {
   190  				b2, err := marshaler.MarshalText()
   191  				return append(b, b2...), err
   192  			}); err != nil {
   193  				err = wrapErrUnsupported(err, "MarshalText method")
   194  				if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
   195  					return internal.NewMarshalerError(va.Addr().Interface(), err, "MarshalText") // unlike unmarshal, always wrapped
   196  				}
   197  				if !isSemanticError(err) && !export.IsIOError(err) {
   198  					err = newMarshalErrorBefore(enc, t, err)
   199  				}
   200  				return err
   201  			}
   202  			return nil
   203  		}
   204  	}
   205  
   206  	if needAddr, ok := implements(t, textAppenderType); ok {
   207  		fncs.nonDefault = true
   208  		prevMarshal := fncs.fnc
   209  		fncs.fnc = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) (err error) {
   210  			if mo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
   211  				((needAddr && va.forcedAddr) ||
   212  					(va.forcedAddr && export.Encoder(enc).Tokens.Last.NeedObjectName() && t.Kind() == reflect.String)) {
   213  				// Do not call AppendText on unaddressable values and map keys of string kind.
   214  				// A map key of pointer kind is dereferenced before reaching here,
   215  				// in which case va.forcedAddr is false and AppendText is still called.
   216  				return prevMarshal(enc, va, mo)
   217  			}
   218  			appender, _ := reflect.TypeAssert[encoding.TextAppender](va.Addr())
   219  			if err := export.Encoder(enc).AppendRaw('"', false, appender.AppendText); err != nil {
   220  				err = wrapErrUnsupported(err, "AppendText method")
   221  				if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
   222  					return internal.NewMarshalerError(va.Addr().Interface(), err, "AppendText") // unlike unmarshal, always wrapped
   223  				}
   224  				if !isSemanticError(err) && !export.IsIOError(err) {
   225  					err = newMarshalErrorBefore(enc, t, err)
   226  				}
   227  				return err
   228  			}
   229  			return nil
   230  		}
   231  	}
   232  
   233  	if needAddr, ok := implements(t, jsonMarshalerType); ok {
   234  		fncs.nonDefault = true
   235  		prevMarshal := fncs.fnc
   236  		fncs.fnc = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
   237  			if mo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
   238  				((needAddr && va.forcedAddr) || export.Encoder(enc).Tokens.Last.NeedObjectName()) {
   239  				// Do not call MarshalJSON on unaddressable values and map keys.
   240  				return prevMarshal(enc, va, mo)
   241  			}
   242  			marshaler, _ := reflect.TypeAssert[Marshaler](va.Addr())
   243  			val, err := marshaler.MarshalJSON()
   244  			if err != nil {
   245  				err = wrapErrUnsupported(err, "MarshalJSON method")
   246  				if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
   247  					return internal.NewMarshalerError(va.Addr().Interface(), err, "MarshalJSON") // unlike unmarshal, always wrapped
   248  				}
   249  				err = newMarshalErrorBefore(enc, t, err)
   250  				return collapseSemanticErrors(err)
   251  			}
   252  			if err := enc.WriteValue(val); err != nil {
   253  				if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
   254  					return internal.NewMarshalerError(va.Addr().Interface(), err, "MarshalJSON") // unlike unmarshal, always wrapped
   255  				}
   256  				if isSyntacticError(err) {
   257  					err = newMarshalErrorBefore(enc, t, err)
   258  				}
   259  				return err
   260  			}
   261  			return nil
   262  		}
   263  	}
   264  
   265  	if needAddr, ok := implements(t, jsonMarshalerToType); ok {
   266  		fncs.nonDefault = true
   267  		prevMarshal := fncs.fnc
   268  		fncs.fnc = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
   269  			if mo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
   270  				((needAddr && va.forcedAddr) || export.Encoder(enc).Tokens.Last.NeedObjectName()) {
   271  				// Do not call MarshalJSONTo on unaddressable values and map keys.
   272  				return prevMarshal(enc, va, mo)
   273  			}
   274  			xe := export.Encoder(enc)
   275  			prevDepth, prevLength := xe.Tokens.DepthLength()
   276  			xe.Flags.Set(jsonflags.WithinArshalCall | 1)
   277  			marshaler, _ := reflect.TypeAssert[MarshalerTo](va.Addr())
   278  			err := marshaler.MarshalJSONTo(enc)
   279  			xe.Flags.Set(jsonflags.WithinArshalCall | 0)
   280  			currDepth, currLength := xe.Tokens.DepthLength()
   281  			if (prevDepth != currDepth || prevLength+1 != currLength) && err == nil {
   282  				err = errNonSingularValue
   283  			}
   284  			if err != nil {
   285  				if errors.Is(err, errors.ErrUnsupported) {
   286  					if prevDepth == currDepth && prevLength == currLength {
   287  						return prevMarshal(enc, va, mo)
   288  					}
   289  					err = errUnsupportedMutation
   290  				}
   291  				if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
   292  					return internal.NewMarshalerError(va.Addr().Interface(), err, "MarshalJSONTo") // unlike unmarshal, always wrapped
   293  				}
   294  				if !export.IsIOError(err) {
   295  					err = newSemanticErrorWithPosition(enc, t, prevDepth, prevLength, err)
   296  				}
   297  				return err
   298  			}
   299  			return nil
   300  		}
   301  	}
   302  
   303  	return fncs
   304  }
   305  
   306  func makeMethodUnmarshaler(fncs *unmarshaler, t reflect.Type) *unmarshaler {
   307  	// Avoid injecting method unmarshaler on the pointer or interface version
   308  	// to avoid ever calling the method on a nil pointer or interface receiver.
   309  	// Let it be injected on the value receiver (which is always addressable).
   310  	if t.Kind() == reflect.Pointer || t.Kind() == reflect.Interface {
   311  		return fncs
   312  	}
   313  
   314  	if _, ok := implements(t, textUnmarshalerType); ok {
   315  		fncs.nonDefault = true
   316  		fncs.fnc = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error {
   317  			xd := export.Decoder(dec)
   318  			var flags jsonwire.ValueFlags
   319  			val, err := xd.ReadValue(&flags)
   320  			if err != nil {
   321  				return err // must be a syntactic or I/O error
   322  			}
   323  			if val.Kind() == 'n' {
   324  				if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) {
   325  					va.SetZero()
   326  				}
   327  				return nil
   328  			}
   329  			if val.Kind() != '"' {
   330  				return newUnmarshalErrorAfter(dec, t, errNonStringValue)
   331  			}
   332  			s := jsonwire.UnquoteMayCopy(val, flags.IsVerbatim())
   333  			unmarshaler, _ := reflect.TypeAssert[encoding.TextUnmarshaler](va.Addr())
   334  			if err := unmarshaler.UnmarshalText(s); err != nil {
   335  				err = wrapErrUnsupported(err, "UnmarshalText method")
   336  				if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
   337  					return err // unlike marshal, never wrapped
   338  				}
   339  				if !isSemanticError(err) && !isSyntacticError(err) && !export.IsIOError(err) {
   340  					err = newUnmarshalErrorAfter(dec, t, err)
   341  				}
   342  				return err
   343  			}
   344  			return nil
   345  		}
   346  	}
   347  
   348  	if _, ok := implements(t, jsonUnmarshalerType); ok {
   349  		fncs.nonDefault = true
   350  		prevUnmarshal := fncs.fnc
   351  		fncs.fnc = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error {
   352  			if uo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
   353  				export.Decoder(dec).Tokens.Last.NeedObjectName() {
   354  				// Do not call UnmarshalJSON on map keys.
   355  				return prevUnmarshal(dec, va, uo)
   356  			}
   357  			val, err := dec.ReadValue()
   358  			if err != nil {
   359  				return err // must be a syntactic or I/O error
   360  			}
   361  			unmarshaler, _ := reflect.TypeAssert[Unmarshaler](va.Addr())
   362  			if err := unmarshaler.UnmarshalJSON(val); err != nil {
   363  				err = wrapErrUnsupported(err, "UnmarshalJSON method")
   364  				if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
   365  					return err // unlike marshal, never wrapped
   366  				}
   367  				err = newUnmarshalErrorAfter(dec, t, err)
   368  				return collapseSemanticErrors(err)
   369  			}
   370  			return nil
   371  		}
   372  	}
   373  
   374  	if _, ok := implements(t, jsonUnmarshalerFromType); ok {
   375  		fncs.nonDefault = true
   376  		prevUnmarshal := fncs.fnc
   377  		fncs.fnc = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error {
   378  			if uo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
   379  				export.Decoder(dec).Tokens.Last.NeedObjectName() {
   380  				// Do not call UnmarshalJSONFrom on map keys.
   381  				return prevUnmarshal(dec, va, uo)
   382  			}
   383  			xd := export.Decoder(dec)
   384  			prevDepth, prevLength := xd.Tokens.DepthLength()
   385  			if prevDepth == 1 && xd.AtEOF() {
   386  				return io.EOF // check EOF early to avoid fn reporting an EOF
   387  			}
   388  			xd.Flags.Set(jsonflags.WithinArshalCall | 1)
   389  			unmarshaler, _ := reflect.TypeAssert[UnmarshalerFrom](va.Addr())
   390  			err := unmarshaler.UnmarshalJSONFrom(dec)
   391  			xd.Flags.Set(jsonflags.WithinArshalCall | 0)
   392  			currDepth, currLength := xd.Tokens.DepthLength()
   393  			if (prevDepth != currDepth || prevLength+1 != currLength) && err == nil {
   394  				err = errNonSingularValue
   395  			}
   396  			if err != nil {
   397  				if errors.Is(err, errors.ErrUnsupported) {
   398  					if prevDepth == currDepth && prevLength == currLength {
   399  						return prevUnmarshal(dec, va, uo)
   400  					}
   401  					err = errUnsupportedMutation
   402  				}
   403  				if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
   404  					if err2 := xd.SkipUntil(prevDepth, prevLength+1); err2 != nil {
   405  						return err2
   406  					}
   407  					return err // unlike marshal, never wrapped
   408  				}
   409  				if !isSyntacticError(err) && !export.IsIOError(err) {
   410  					err = newSemanticErrorWithPosition(dec, t, prevDepth, prevLength, err)
   411  				}
   412  				return err
   413  			}
   414  			return nil
   415  		}
   416  	}
   417  
   418  	return fncs
   419  }
   420  
   421  // implementsAny is like t.Implements(ifaceType) for a list of interfaces,
   422  // but checks whether either t or reflect.PointerTo(t) implements the interface.
   423  func implementsAny(t reflect.Type, ifaceTypes ...reflect.Type) bool {
   424  	for _, ifaceType := range ifaceTypes {
   425  		if _, ok := implements(t, ifaceType); ok {
   426  			return true
   427  		}
   428  	}
   429  	return false
   430  }
   431  
   432  // implements is like t.Implements(ifaceType) but checks whether
   433  // either t or reflect.PointerTo(t) implements the interface.
   434  // It also reports whether the value needs to be addressed
   435  // in order to satisfy the interface.
   436  func implements(t, ifaceType reflect.Type) (needAddr, ok bool) {
   437  	switch {
   438  	case t.Implements(ifaceType):
   439  		return false, true
   440  	case reflect.PointerTo(t).Implements(ifaceType):
   441  		return true, true
   442  	default:
   443  		return false, false
   444  	}
   445  }
   446  

View as plain text