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

View as plain text