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

View as plain text