Source file src/encoding/json/v2_stream.go

     1  // Copyright 2010 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  	"bytes"
    11  	"errors"
    12  	"io"
    13  
    14  	"encoding/json/jsontext"
    15  	jsonv2 "encoding/json/v2"
    16  )
    17  
    18  // A Decoder reads and decodes JSON values from an input stream.
    19  type Decoder struct {
    20  	dec  *jsontext.Decoder
    21  	opts jsonv2.Options
    22  	err  error
    23  }
    24  
    25  // NewDecoder returns a new decoder that reads from r.
    26  //
    27  // The decoder introduces its own buffering and may
    28  // read data from r beyond the JSON values requested.
    29  func NewDecoder(r io.Reader) *Decoder {
    30  	// Hide bytes.Buffer from jsontext since it implements optimizations that
    31  	// also limits certain ways it could be used. For example, one cannot write
    32  	// to the bytes.Buffer while it is in use by jsontext.Decoder.
    33  	if _, ok := r.(*bytes.Buffer); ok {
    34  		r = struct{ io.Reader }{r}
    35  	}
    36  
    37  	dec := new(Decoder)
    38  	dec.opts = DefaultOptionsV1()
    39  	dec.dec = jsontext.NewDecoder(r, dec.opts)
    40  	return dec
    41  }
    42  
    43  // UseNumber causes the Decoder to unmarshal a number into an
    44  // interface value as a [Number] instead of as a float64.
    45  func (dec *Decoder) UseNumber() {
    46  	if useNumber, _ := jsonv2.GetOption(dec.opts, unmarshalAnyWithRawNumber); !useNumber {
    47  		dec.opts = jsonv2.JoinOptions(dec.opts, unmarshalAnyWithRawNumber(true))
    48  	}
    49  }
    50  
    51  // DisallowUnknownFields causes the Decoder to return an error when the destination
    52  // is a struct and the input contains object keys which do not match any
    53  // non-ignored, exported fields in the destination.
    54  func (dec *Decoder) DisallowUnknownFields() {
    55  	if reject, _ := jsonv2.GetOption(dec.opts, jsonv2.RejectUnknownMembers); !reject {
    56  		dec.opts = jsonv2.JoinOptions(dec.opts, jsonv2.RejectUnknownMembers(true))
    57  	}
    58  }
    59  
    60  // Decode reads the next JSON-encoded value from its
    61  // input and stores it in the value pointed to by v.
    62  //
    63  // See the documentation for [Unmarshal] for details about
    64  // the conversion of JSON into a Go value.
    65  func (dec *Decoder) Decode(v any) error {
    66  	if dec.err != nil {
    67  		return dec.err
    68  	}
    69  	b, err := dec.dec.ReadValue()
    70  	if err != nil {
    71  		dec.err = transformSyntacticError(err)
    72  		if dec.err.Error() == errUnexpectedEnd.Error() {
    73  			// NOTE: Decode has always been inconsistent with Unmarshal
    74  			// with regard to the exact error value for truncated input.
    75  			dec.err = io.ErrUnexpectedEOF
    76  		}
    77  		return dec.err
    78  	}
    79  	return jsonv2.Unmarshal(b, v, dec.opts)
    80  }
    81  
    82  // Buffered returns a reader of the data remaining in the Decoder's
    83  // buffer. The reader is valid until the next call to [Decoder.Decode].
    84  func (dec *Decoder) Buffered() io.Reader {
    85  	return bytes.NewReader(dec.dec.UnreadBuffer())
    86  }
    87  
    88  // An Encoder writes JSON values to an output stream.
    89  type Encoder struct {
    90  	w    io.Writer
    91  	opts jsonv2.Options
    92  	err  error
    93  
    94  	buf       bytes.Buffer
    95  	indentBuf bytes.Buffer
    96  
    97  	indentPrefix string
    98  	indentValue  string
    99  }
   100  
   101  // NewEncoder returns a new encoder that writes to w.
   102  func NewEncoder(w io.Writer) *Encoder {
   103  	enc := new(Encoder)
   104  	enc.w = w
   105  	enc.opts = DefaultOptionsV1()
   106  	return enc
   107  }
   108  
   109  // Encode writes the JSON encoding of v to the stream,
   110  // followed by a newline character.
   111  //
   112  // See the documentation for [Marshal] for details about the
   113  // conversion of Go values to JSON.
   114  func (enc *Encoder) Encode(v any) error {
   115  	if enc.err != nil {
   116  		return enc.err
   117  	}
   118  
   119  	buf := &enc.buf
   120  	buf.Reset()
   121  	if err := jsonv2.MarshalWrite(buf, v, enc.opts); err != nil {
   122  		return err
   123  	}
   124  	if len(enc.indentPrefix)+len(enc.indentValue) > 0 {
   125  		enc.indentBuf.Reset()
   126  		if err := Indent(&enc.indentBuf, buf.Bytes(), enc.indentPrefix, enc.indentValue); err != nil {
   127  			return err
   128  		}
   129  		buf = &enc.indentBuf
   130  	}
   131  	buf.WriteByte('\n')
   132  
   133  	if _, err := enc.w.Write(buf.Bytes()); err != nil {
   134  		enc.err = err
   135  		return err
   136  	}
   137  	return nil
   138  }
   139  
   140  // SetIndent instructs the encoder to format each subsequent encoded
   141  // value as if indented by the package-level function Indent(dst, src, prefix, indent).
   142  // Calling SetIndent("", "") disables indentation.
   143  func (enc *Encoder) SetIndent(prefix, indent string) {
   144  	enc.indentPrefix = prefix
   145  	enc.indentValue = indent
   146  }
   147  
   148  // SetEscapeHTML specifies whether problematic HTML characters
   149  // should be escaped inside JSON quoted strings.
   150  // The default behavior is to escape &, <, and > to \u0026, \u003c, and \u003e
   151  // to avoid certain safety problems that can arise when embedding JSON in HTML.
   152  //
   153  // In non-HTML settings where the escaping interferes with the readability
   154  // of the output, SetEscapeHTML(false) disables this behavior.
   155  func (enc *Encoder) SetEscapeHTML(on bool) {
   156  	if escape, _ := jsonv2.GetOption(enc.opts, jsontext.EscapeForHTML); escape != on {
   157  		enc.opts = jsonv2.JoinOptions(enc.opts, jsontext.EscapeForHTML(on))
   158  	}
   159  }
   160  
   161  // RawMessage is a raw encoded JSON value.
   162  // It implements [Marshaler] and [Unmarshaler] and can
   163  // be used to delay JSON decoding or precompute a JSON encoding.
   164  type RawMessage = jsontext.Value
   165  
   166  // A Token holds a value of one of these types:
   167  //
   168  //   - [Delim], for the four JSON delimiters [ ] { }
   169  //   - bool, for JSON booleans
   170  //   - float64, for JSON numbers
   171  //   - [Number], for JSON numbers
   172  //   - string, for JSON string literals
   173  //   - nil, for JSON null
   174  type Token any
   175  
   176  // A Delim is a JSON array or object delimiter, one of [ ] { or }.
   177  type Delim rune
   178  
   179  func (d Delim) String() string {
   180  	return string(d)
   181  }
   182  
   183  // Token returns the next JSON token in the input stream.
   184  // At the end of the input stream, Token returns nil, [io.EOF].
   185  //
   186  // Token guarantees that the delimiters [ ] { } it returns are
   187  // properly nested and matched: if Token encounters an unexpected
   188  // delimiter in the input, it will return an error.
   189  //
   190  // The input stream consists of basic JSON values—bool, string,
   191  // number, and null—along with delimiters [ ] { } of type [Delim]
   192  // to mark the start and end of arrays and objects.
   193  // Commas and colons are elided.
   194  func (dec *Decoder) Token() (Token, error) {
   195  	tok, err := dec.dec.ReadToken()
   196  	if err != nil {
   197  		// Historically, v1 would report just [io.EOF] if
   198  		// the stream is a prefix of a valid JSON value.
   199  		// It reports an unwrapped [io.ErrUnexpectedEOF] if
   200  		// truncated within a JSON token such as a literal, number, or string.
   201  		if errors.Is(err, io.ErrUnexpectedEOF) {
   202  			if len(bytes.Trim(dec.dec.UnreadBuffer(), " \r\n\t,:")) == 0 {
   203  				return nil, io.EOF
   204  			}
   205  			return nil, io.ErrUnexpectedEOF
   206  		}
   207  		return nil, transformSyntacticError(err)
   208  	}
   209  	switch k := tok.Kind(); k {
   210  	case 'n':
   211  		return nil, nil
   212  	case 'f':
   213  		return false, nil
   214  	case 't':
   215  		return true, nil
   216  	case '"':
   217  		return tok.String(), nil
   218  	case '0':
   219  		if useNumber, _ := jsonv2.GetOption(dec.opts, unmarshalAnyWithRawNumber); useNumber {
   220  			return Number(tok.String()), nil
   221  		}
   222  		return tok.Float(), nil
   223  	case '{', '}', '[', ']':
   224  		return Delim(k), nil
   225  	default:
   226  		panic("unreachable")
   227  	}
   228  }
   229  
   230  // More reports whether there is another element in the
   231  // current array or object being parsed.
   232  func (dec *Decoder) More() bool {
   233  	k := dec.dec.PeekKind()
   234  	return k > 0 && k != ']' && k != '}'
   235  }
   236  
   237  // InputOffset returns the input stream byte offset of the current decoder position.
   238  // The offset gives the location of the end of the most recently returned token
   239  // and the beginning of the next token.
   240  func (dec *Decoder) InputOffset() int64 {
   241  	return dec.dec.InputOffset()
   242  }
   243  

View as plain text