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

View as plain text