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

View as plain text