Source File
v2_stream.go
Belonging Package
encoding/json
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build goexperiment.jsonv2
package json
import (
jsonv2
)
// A Decoder reads and decodes JSON values from an input stream.
type Decoder struct {
dec *jsontext.Decoder
opts jsonv2.Options
err error
}
// NewDecoder returns a new decoder that reads from r.
//
// The decoder introduces its own buffering and may
// read data from r beyond the JSON values requested.
func ( io.Reader) *Decoder {
// Hide bytes.Buffer from jsontext since it implements optimizations that
// also limits certain ways it could be used. For example, one cannot write
// to the bytes.Buffer while it is in use by jsontext.Decoder.
if , := .(*bytes.Buffer); {
= struct{ io.Reader }{}
}
:= new(Decoder)
.opts = DefaultOptionsV1()
.dec = jsontext.NewDecoder(, .opts)
return
}
// UseNumber causes the Decoder to unmarshal a number into an
// interface value as a [Number] instead of as a float64.
func ( *Decoder) () {
if , := jsonv2.GetOption(.opts, unmarshalAnyWithRawNumber); ! {
.opts = jsonv2.JoinOptions(.opts, unmarshalAnyWithRawNumber(true))
}
}
// DisallowUnknownFields causes the Decoder to return an error when the destination
// is a struct and the input contains object keys which do not match any
// non-ignored, exported fields in the destination.
func ( *Decoder) () {
if , := jsonv2.GetOption(.opts, jsonv2.RejectUnknownMembers); ! {
.opts = jsonv2.JoinOptions(.opts, jsonv2.RejectUnknownMembers(true))
}
}
// Decode reads the next JSON-encoded value from its
// input and stores it in the value pointed to by v.
//
// See the documentation for [Unmarshal] for details about
// the conversion of JSON into a Go value.
func ( *Decoder) ( any) error {
if .err != nil {
return .err
}
, := .dec.ReadValue()
if != nil {
.err = transformSyntacticError()
if .err == errUnexpectedEnd {
// NOTE: Decode has always been inconsistent with Unmarshal
// with regard to the exact error value for truncated input.
.err = io.ErrUnexpectedEOF
}
return .err
}
return jsonv2.Unmarshal(, , .opts)
}
// Buffered returns a reader of the data remaining in the Decoder's
// buffer. The reader is valid until the next call to [Decoder.Decode].
func ( *Decoder) () io.Reader {
return bytes.NewReader(.dec.UnreadBuffer())
}
// An Encoder writes JSON values to an output stream.
type Encoder struct {
w io.Writer
opts jsonv2.Options
err error
buf bytes.Buffer
indentBuf bytes.Buffer
indentPrefix string
indentValue string
}
// NewEncoder returns a new encoder that writes to w.
func ( io.Writer) *Encoder {
:= new(Encoder)
.w =
.opts = DefaultOptionsV1()
return
}
// Encode writes the JSON encoding of v to the stream,
// followed by a newline character.
//
// See the documentation for [Marshal] for details about the
// conversion of Go values to JSON.
func ( *Encoder) ( any) error {
if .err != nil {
return .err
}
:= &.buf
.Reset()
if := jsonv2.MarshalWrite(, , .opts); != nil {
return
}
if len(.indentPrefix)+len(.indentValue) > 0 {
.indentBuf.Reset()
if := Indent(&.indentBuf, .Bytes(), .indentPrefix, .indentValue); != nil {
return
}
= &.indentBuf
}
.WriteByte('\n')
if , := .w.Write(.Bytes()); != nil {
.err =
return
}
return nil
}
// SetIndent instructs the encoder to format each subsequent encoded
// value as if indented by the package-level function Indent(dst, src, prefix, indent).
// Calling SetIndent("", "") disables indentation.
func ( *Encoder) (, string) {
.indentPrefix =
.indentValue =
}
// SetEscapeHTML specifies whether problematic HTML characters
// should be escaped inside JSON quoted strings.
// The default behavior is to escape &, <, and > to \u0026, \u003c, and \u003e
// to avoid certain safety problems that can arise when embedding JSON in HTML.
//
// In non-HTML settings where the escaping interferes with the readability
// of the output, SetEscapeHTML(false) disables this behavior.
func ( *Encoder) ( bool) {
if , := jsonv2.GetOption(.opts, jsontext.EscapeForHTML); != {
.opts = jsonv2.JoinOptions(.opts, jsontext.EscapeForHTML())
}
}
// RawMessage is a raw encoded JSON value.
// It implements [Marshaler] and [Unmarshaler] and can
// be used to delay JSON decoding or precompute a JSON encoding.
type RawMessage = jsontext.Value
// A Token holds a value of one of these types:
//
// - [Delim], for the four JSON delimiters [ ] { }
// - bool, for JSON booleans
// - float64, for JSON numbers
// - [Number], for JSON numbers
// - string, for JSON string literals
// - nil, for JSON null
type Token any
// A Delim is a JSON array or object delimiter, one of [ ] { or }.
type Delim rune
func ( Delim) () string {
return string()
}
// Token returns the next JSON token in the input stream.
// At the end of the input stream, Token returns nil, [io.EOF].
//
// Token guarantees that the delimiters [ ] { } it returns are
// properly nested and matched: if Token encounters an unexpected
// delimiter in the input, it will return an error.
//
// The input stream consists of basic JSON values—bool, string,
// number, and null—along with delimiters [ ] { } of type [Delim]
// to mark the start and end of arrays and objects.
// Commas and colons are elided.
func ( *Decoder) () (Token, error) {
, := .dec.ReadToken()
if != nil {
return nil, transformSyntacticError()
}
switch := .Kind(); {
case 'n':
return nil, nil
case 'f':
return false, nil
case 't':
return true, nil
case '"':
return .String(), nil
case '0':
if , := jsonv2.GetOption(.opts, unmarshalAnyWithRawNumber); {
return Number(.String()), nil
}
return .Float(), nil
case '{', '}', '[', ']':
return Delim(), nil
default:
panic("unreachable")
}
}
// More reports whether there is another element in the
// current array or object being parsed.
func ( *Decoder) () bool {
:= .dec.PeekKind()
return > 0 && != ']' && != '}'
}
// InputOffset returns the input stream byte offset of the current decoder position.
// The offset gives the location of the end of the most recently returned token
// and the beginning of the next token.
func ( *Decoder) () int64 {
return .dec.InputOffset()
}
![]() |
The pages are generated with Golds v0.7.7-preview. (GOOS=linux GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds. |