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 a hard dependency on the "jsontext" package.
    42  //
    43  // It is recommended that implementations return a buffer that is safe
    44  // for the caller to retain and potentially mutate.
    45  //
    46  // If the returned error is a [SemanticError], then unpopulated fields
    47  // of the error may be populated by [json] with additional context.
    48  // Errors of other types are wrapped within a [SemanticError].
    49  type Marshaler interface {
    50  	MarshalJSON() ([]byte, error)
    51  }
    52  
    53  // MarshalerTo is implemented by types that can marshal themselves.
    54  // It is recommended that types implement MarshalerTo instead of [Marshaler]
    55  // since this is both more performant and flexible.
    56  // If a type implements both Marshaler and MarshalerTo,
    57  // then MarshalerTo takes precedence. In such a case, both implementations
    58  // should aim to have equivalent behavior for the default marshal options.
    59  //
    60  // The implementation must write only one JSON value to the Encoder.
    61  // Alternatively, it may return [errors.ErrUnsupported] without mutating
    62  // the Encoder. The "json" package calling the method will
    63  // use the next available JSON representation for the receiver type.
    64  // Implementations must not retain the pointer to [jsontext.Encoder].
    65  //
    66  // If the returned error is a [SemanticError], then unpopulated fields
    67  // of the error may be populated by [json] with additional context.
    68  // Errors of other types are wrapped within a [SemanticError],
    69  // unless it is an IO error.
    70  //
    71  // The MarshalJSONTo method should not be directly called as it may
    72  // return sentinel errors that need special handling.
    73  // Users should instead call [MarshalEncode], which handles such cases.
    74  type MarshalerTo interface {
    75  	MarshalJSONTo(*jsontext.Encoder) error
    76  }
    77  
    78  // Unmarshaler is implemented by types that can unmarshal themselves.
    79  // It is recommended that types implement [UnmarshalerFrom] unless the implementation
    80  // is trying to avoid a hard dependency on the "jsontext" package.
    81  //
    82  // The input can be assumed to be a valid encoding of a JSON value
    83  // if called from unmarshal functionality in this package.
    84  // UnmarshalJSON must copy the JSON data if it is retained after returning.
    85  // It is recommended that UnmarshalJSON implement merge semantics when
    86  // unmarshaling into a pre-populated value.
    87  //
    88  // Implementations must not retain or mutate the input []byte.
    89  //
    90  // If the returned error is a [SemanticError], then unpopulated fields
    91  // of the error may be populated by [json] with additional context.
    92  // Errors of other types are wrapped within a [SemanticError].
    93  type Unmarshaler interface {
    94  	UnmarshalJSON([]byte) error
    95  }
    96  
    97  // UnmarshalerFrom is implemented by types that can unmarshal themselves.
    98  // It is recommended that types implement UnmarshalerFrom instead of [Unmarshaler]
    99  // since this is both more performant and flexible.
   100  // If a type implements both Unmarshaler and UnmarshalerFrom,
   101  // then UnmarshalerFrom takes precedence. In such a case, both implementations
   102  // should aim to have equivalent behavior for the default unmarshal options.
   103  //
   104  // The implementation must read only one JSON value from the Decoder.
   105  // It is recommended that UnmarshalJSONFrom implement merge semantics when
   106  // unmarshaling into a pre-populated value.
   107  // Alternatively, it may return [errors.ErrUnsupported] without mutating
   108  // the Decoder. The "json" package calling the method will
   109  // use the next available JSON representation for the receiver type.
   110  // Implementations must not retain the pointer to [jsontext.Decoder].
   111  //
   112  // If the returned error is a [SemanticError], then unpopulated fields
   113  // of the error may be populated by [json] with additional context.
   114  // Errors of other types are wrapped within a [SemanticError],
   115  // unless it is a [jsontext.SyntacticError] or an IO error.
   116  //
   117  // The UnmarshalJSONFrom method should not be directly called as it may
   118  // return sentinel errors that need special handling.
   119  // Users should instead call [UnmarshalDecode], which handles such cases.
   120  type UnmarshalerFrom interface {
   121  	UnmarshalJSONFrom(*jsontext.Decoder) error
   122  }
   123  
   124  func makeMethodArshaler(fncs *arshaler, t reflect.Type) *arshaler {
   125  	// Avoid injecting method arshaler on the pointer or interface version
   126  	// to avoid ever calling the method on a nil pointer or interface receiver.
   127  	// Let it be injected on the value receiver (which is always addressable).
   128  	if t.Kind() == reflect.Pointer || t.Kind() == reflect.Interface {
   129  		return fncs
   130  	}
   131  
   132  	if needAddr, ok := implements(t, textMarshalerType); ok {
   133  		fncs.nonDefault = true
   134  		prevMarshal := fncs.marshal
   135  		fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
   136  			if mo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
   137  				(needAddr && va.forcedAddr) {
   138  				return prevMarshal(enc, va, mo)
   139  			}
   140  			marshaler, _ := reflect.TypeAssert[encoding.TextMarshaler](va.Addr())
   141  			if err := export.Encoder(enc).AppendRaw('"', false, func(b []byte) ([]byte, error) {
   142  				b2, err := marshaler.MarshalText()
   143  				return append(b, b2...), err
   144  			}); err != nil {
   145  				err = wrapErrUnsupported(err, "MarshalText method")
   146  				if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
   147  					return internal.NewMarshalerError(va.Addr().Interface(), err, "MarshalText") // unlike unmarshal, always wrapped
   148  				}
   149  				if !isSemanticError(err) && !export.IsIOError(err) {
   150  					err = newMarshalErrorBefore(enc, t, err)
   151  				}
   152  				return err
   153  			}
   154  			return nil
   155  		}
   156  	}
   157  
   158  	if needAddr, ok := implements(t, textAppenderType); ok {
   159  		fncs.nonDefault = true
   160  		prevMarshal := fncs.marshal
   161  		fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) (err error) {
   162  			if mo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
   163  				(needAddr && va.forcedAddr) {
   164  				return prevMarshal(enc, va, mo)
   165  			}
   166  			appender, _ := reflect.TypeAssert[encoding.TextAppender](va.Addr())
   167  			if err := export.Encoder(enc).AppendRaw('"', false, appender.AppendText); err != nil {
   168  				err = wrapErrUnsupported(err, "AppendText method")
   169  				if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
   170  					return internal.NewMarshalerError(va.Addr().Interface(), err, "AppendText") // unlike unmarshal, always wrapped
   171  				}
   172  				if !isSemanticError(err) && !export.IsIOError(err) {
   173  					err = newMarshalErrorBefore(enc, t, err)
   174  				}
   175  				return err
   176  			}
   177  			return nil
   178  		}
   179  	}
   180  
   181  	if needAddr, ok := implements(t, jsonMarshalerType); ok {
   182  		fncs.nonDefault = true
   183  		prevMarshal := fncs.marshal
   184  		fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
   185  			if mo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
   186  				((needAddr && va.forcedAddr) || export.Encoder(enc).Tokens.Last.NeedObjectName()) {
   187  				return prevMarshal(enc, va, mo)
   188  			}
   189  			marshaler, _ := reflect.TypeAssert[Marshaler](va.Addr())
   190  			val, err := marshaler.MarshalJSON()
   191  			if err != nil {
   192  				err = wrapErrUnsupported(err, "MarshalJSON method")
   193  				if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
   194  					return internal.NewMarshalerError(va.Addr().Interface(), err, "MarshalJSON") // unlike unmarshal, always wrapped
   195  				}
   196  				err = newMarshalErrorBefore(enc, t, err)
   197  				return collapseSemanticErrors(err)
   198  			}
   199  			if err := enc.WriteValue(val); err != nil {
   200  				if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
   201  					return internal.NewMarshalerError(va.Addr().Interface(), err, "MarshalJSON") // unlike unmarshal, always wrapped
   202  				}
   203  				if isSyntacticError(err) {
   204  					err = newMarshalErrorBefore(enc, t, err)
   205  				}
   206  				return err
   207  			}
   208  			return nil
   209  		}
   210  	}
   211  
   212  	if needAddr, ok := implements(t, jsonMarshalerToType); ok {
   213  		fncs.nonDefault = true
   214  		prevMarshal := fncs.marshal
   215  		fncs.marshal = func(enc *jsontext.Encoder, va addressableValue, mo *jsonopts.Struct) error {
   216  			if mo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
   217  				((needAddr && va.forcedAddr) || export.Encoder(enc).Tokens.Last.NeedObjectName()) {
   218  				return prevMarshal(enc, va, mo)
   219  			}
   220  			xe := export.Encoder(enc)
   221  			prevDepth, prevLength := xe.Tokens.DepthLength()
   222  			xe.Flags.Set(jsonflags.WithinArshalCall | 1)
   223  			marshaler, _ := reflect.TypeAssert[MarshalerTo](va.Addr())
   224  			err := marshaler.MarshalJSONTo(enc)
   225  			xe.Flags.Set(jsonflags.WithinArshalCall | 0)
   226  			currDepth, currLength := xe.Tokens.DepthLength()
   227  			if (prevDepth != currDepth || prevLength+1 != currLength) && err == nil {
   228  				err = errNonSingularValue
   229  			}
   230  			if err != nil {
   231  				if errors.Is(err, errors.ErrUnsupported) {
   232  					if prevDepth == currDepth && prevLength == currLength {
   233  						return prevMarshal(enc, va, mo)
   234  					}
   235  					err = errUnsupportedMutation
   236  				}
   237  				if mo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
   238  					return internal.NewMarshalerError(va.Addr().Interface(), err, "MarshalJSONTo") // unlike unmarshal, always wrapped
   239  				}
   240  				if !export.IsIOError(err) {
   241  					err = newSemanticErrorWithPosition(enc, t, prevDepth, prevLength, err)
   242  				}
   243  				return err
   244  			}
   245  			return nil
   246  		}
   247  	}
   248  
   249  	if _, ok := implements(t, textUnmarshalerType); ok {
   250  		fncs.nonDefault = true
   251  		fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error {
   252  			xd := export.Decoder(dec)
   253  			var flags jsonwire.ValueFlags
   254  			val, err := xd.ReadValue(&flags)
   255  			if err != nil {
   256  				return err // must be a syntactic or I/O error
   257  			}
   258  			if val.Kind() == 'n' {
   259  				if !uo.Flags.Get(jsonflags.MergeWithLegacySemantics) {
   260  					va.SetZero()
   261  				}
   262  				return nil
   263  			}
   264  			if val.Kind() != '"' {
   265  				return newUnmarshalErrorAfter(dec, t, errNonStringValue)
   266  			}
   267  			s := jsonwire.UnquoteMayCopy(val, flags.IsVerbatim())
   268  			unmarshaler, _ := reflect.TypeAssert[encoding.TextUnmarshaler](va.Addr())
   269  			if err := unmarshaler.UnmarshalText(s); err != nil {
   270  				err = wrapErrUnsupported(err, "UnmarshalText method")
   271  				if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
   272  					return err // unlike marshal, never wrapped
   273  				}
   274  				if !isSemanticError(err) && !isSyntacticError(err) && !export.IsIOError(err) {
   275  					err = newUnmarshalErrorAfter(dec, t, err)
   276  				}
   277  				return err
   278  			}
   279  			return nil
   280  		}
   281  	}
   282  
   283  	if _, ok := implements(t, jsonUnmarshalerType); ok {
   284  		fncs.nonDefault = true
   285  		prevUnmarshal := fncs.unmarshal
   286  		fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error {
   287  			if uo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
   288  				export.Decoder(dec).Tokens.Last.NeedObjectName() {
   289  				return prevUnmarshal(dec, va, uo)
   290  			}
   291  			val, err := dec.ReadValue()
   292  			if err != nil {
   293  				return err // must be a syntactic or I/O error
   294  			}
   295  			unmarshaler, _ := reflect.TypeAssert[Unmarshaler](va.Addr())
   296  			if err := unmarshaler.UnmarshalJSON(val); err != nil {
   297  				err = wrapErrUnsupported(err, "UnmarshalJSON method")
   298  				if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
   299  					return err // unlike marshal, never wrapped
   300  				}
   301  				err = newUnmarshalErrorAfter(dec, t, err)
   302  				return collapseSemanticErrors(err)
   303  			}
   304  			return nil
   305  		}
   306  	}
   307  
   308  	if _, ok := implements(t, jsonUnmarshalerFromType); ok {
   309  		fncs.nonDefault = true
   310  		prevUnmarshal := fncs.unmarshal
   311  		fncs.unmarshal = func(dec *jsontext.Decoder, va addressableValue, uo *jsonopts.Struct) error {
   312  			if uo.Flags.Get(jsonflags.CallMethodsWithLegacySemantics) &&
   313  				export.Decoder(dec).Tokens.Last.NeedObjectName() {
   314  				return prevUnmarshal(dec, va, uo)
   315  			}
   316  			xd := export.Decoder(dec)
   317  			prevDepth, prevLength := xd.Tokens.DepthLength()
   318  			if prevDepth == 1 && xd.AtEOF() {
   319  				return io.EOF // check EOF early to avoid fn reporting an EOF
   320  			}
   321  			xd.Flags.Set(jsonflags.WithinArshalCall | 1)
   322  			unmarshaler, _ := reflect.TypeAssert[UnmarshalerFrom](va.Addr())
   323  			err := unmarshaler.UnmarshalJSONFrom(dec)
   324  			xd.Flags.Set(jsonflags.WithinArshalCall | 0)
   325  			currDepth, currLength := xd.Tokens.DepthLength()
   326  			if (prevDepth != currDepth || prevLength+1 != currLength) && err == nil {
   327  				err = errNonSingularValue
   328  			}
   329  			if err != nil {
   330  				if errors.Is(err, errors.ErrUnsupported) {
   331  					if prevDepth == currDepth && prevLength == currLength {
   332  						return prevUnmarshal(dec, va, uo)
   333  					}
   334  					err = errUnsupportedMutation
   335  				}
   336  				if uo.Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) {
   337  					if err2 := xd.SkipUntil(prevDepth, prevLength+1); err2 != nil {
   338  						return err2
   339  					}
   340  					return err // unlike marshal, never wrapped
   341  				}
   342  				if !isSyntacticError(err) && !export.IsIOError(err) {
   343  					err = newSemanticErrorWithPosition(dec, t, prevDepth, prevLength, err)
   344  				}
   345  				return err
   346  			}
   347  			return nil
   348  		}
   349  	}
   350  
   351  	return fncs
   352  }
   353  
   354  // implementsAny is like t.Implements(ifaceType) for a list of interfaces,
   355  // but checks whether either t or reflect.PointerTo(t) implements the interface.
   356  func implementsAny(t reflect.Type, ifaceTypes ...reflect.Type) bool {
   357  	for _, ifaceType := range ifaceTypes {
   358  		if _, ok := implements(t, ifaceType); ok {
   359  			return true
   360  		}
   361  	}
   362  	return false
   363  }
   364  
   365  // implements is like t.Implements(ifaceType) but checks whether
   366  // either t or reflect.PointerTo(t) implements the interface.
   367  // It also reports whether the value needs to be addressed
   368  // in order to satisfy the interface.
   369  func implements(t, ifaceType reflect.Type) (needAddr, ok bool) {
   370  	switch {
   371  	case t.Implements(ifaceType):
   372  		return false, true
   373  	case reflect.PointerTo(t).Implements(ifaceType):
   374  		return true, true
   375  	default:
   376  		return false, false
   377  	}
   378  }
   379  

View as plain text