package  jsonimport  (	"bytes" 	"errors" 	"io" )type  Decoder  struct  {	r        io .Reader 	buf      []byte 	d        decodeState 	scanp    int    	scanned  int64  	scan     scanner 	err      error 	tokenState  int 	tokenStack  []int }func  NewDecoder r  io .Reader ) *Decoder  {	return  &Decoder {r : r }}func  (dec  *Decoder ) UseNumber dec .d .useNumber  = true  }func  (dec  *Decoder ) DisallowUnknownFields dec .d .disallowUnknownFields  = true  }func  (dec  *Decoder ) Decode v  any ) error  {	if  dec .err  != nil  {		return  dec .err 	}	if  err  := dec .tokenPrepareForDecode (); err  != nil  {		return  err 	}	if  !dec .tokenValueAllowed () {		return  &SyntaxError {msg : "not at beginning of value" , Offset : dec .InputOffset ()}	}		n , err  := dec .readValue ()	if  err  != nil  {		return  err 	}	dec .d .init (dec .buf [dec .scanp  : dec .scanp +n ])	dec .scanp  += n 		err  = dec .d .unmarshal (v )		dec .tokenValueEnd ()	return  err }func  (dec  *Decoder ) Buffered io .Reader  {	return  bytes .NewReader (dec .buf [dec .scanp :])}func  (dec  *Decoder ) readValue int , error ) {	dec .scan .reset ()	scanp  := dec .scanp 	var  err  error Input :		for  scanp  >= 0  {				for  ; scanp  < len (dec .buf ); scanp ++ {			c  := dec .buf [scanp ]			dec .scan .bytes ++			switch  dec .scan .step (&dec .scan , c ) {			case  scanEnd :								dec .scan .bytes --				break  Input 			case  scanEndObject , scanEndArray :								if  stateEndValue (&dec .scan , ' ' ) == scanEnd  {					scanp ++					break  Input 				}			case  scanError :				dec .err  = dec .scan .err 				return  0 , dec .scan .err 			}		}				if  err  != nil  {			if  err  == io .EOF  {				if  dec .scan .step (&dec .scan , ' ' ) == scanEnd  {					break  Input 				}				if  nonSpace (dec .buf ) {					err  = io .ErrUnexpectedEOF 				}			}			dec .err  = err 			return  0 , err 		}		n  := scanp  - dec .scanp 		err  = dec .refill ()		scanp  = dec .scanp  + n 	}	return  scanp  - dec .scanp , nil }func  (dec  *Decoder ) refill error  {		if  dec .scanp  > 0  {		dec .scanned  += int64 (dec .scanp )		n  := copy (dec .buf , dec .buf [dec .scanp :])		dec .buf  = dec .buf [:n ]		dec .scanp  = 0 	}		const  minRead  = 512 	if  cap (dec .buf )-len (dec .buf ) < minRead  {		newBuf  := make ([]byte , len (dec .buf ), 2 *cap (dec .buf )+minRead )		copy (newBuf , dec .buf )		dec .buf  = newBuf 	}		n , err  := dec .r .Read (dec .buf [len (dec .buf ):cap (dec .buf )])	dec .buf  = dec .buf [0  : len (dec .buf )+n ]	return  err }func  nonSpace b  []byte ) bool  {	for  _ , c  := range  b  {		if  !isSpace (c ) {			return  true 		}	}	return  false }type  Encoder  struct  {	w           io .Writer 	err         error 	escapeHTML  bool 	indentBuf     []byte 	indentPrefix  string 	indentValue   string }func  NewEncoder w  io .Writer ) *Encoder  {	return  &Encoder {w : w , escapeHTML : true }}func  (enc  *Encoder ) Encode v  any ) error  {	if  enc .err  != nil  {		return  enc .err 	}	e  := newEncodeState ()	defer  encodeStatePool .Put (e )	err  := e .marshal (v , encOpts {escapeHTML : enc .escapeHTML })	if  err  != nil  {		return  err 	}		e .WriteByte ('\n' )	b  := e .Bytes ()	if  enc .indentPrefix  != ""  || enc .indentValue  != ""  {		enc .indentBuf , err  = appendIndent (enc .indentBuf [:0 ], b , enc .indentPrefix , enc .indentValue )		if  err  != nil  {			return  err 		}		b  = enc .indentBuf 	}	if  _, err  = enc .w .Write (b ); err  != nil  {		enc .err  = err 	}	return  err }func  (enc  *Encoder ) SetIndent prefix , indent  string ) {	enc .indentPrefix  = prefix 	enc .indentValue  = indent }func  (enc  *Encoder ) SetEscapeHTML on  bool ) {	enc .escapeHTML  = on }type  RawMessage  []byte func  (m  RawMessage ) MarshalJSON byte , error ) {	if  m  == nil  {		return  []byte ("null" ), nil 	}	return  m , nil }func  (m  *RawMessage ) UnmarshalJSON data  []byte ) error  {	if  m  == nil  {		return  errors .New ("json.RawMessage: UnmarshalJSON on nil pointer" )	}	*m  = append ((*m )[0 :0 ], data ...)	return  nil }var  _ Marshaler  = (*RawMessage )(nil )var  _ Unmarshaler  = (*RawMessage )(nil )type  Token  any const  (	tokenTopValue  = iota 	tokenArrayStart 	tokenArrayValue 	tokenArrayComma 	tokenObjectStart 	tokenObjectKey 	tokenObjectColon 	tokenObjectValue 	tokenObjectComma )func  (dec  *Decoder ) tokenPrepareForDecode error  {		switch  dec .tokenState  {	case  tokenArrayComma :		c , err  := dec .peek ()		if  err  != nil  {			return  err 		}		if  c  != ','  {			return  &SyntaxError {"expected comma after array element" , dec .InputOffset ()}		}		dec .scanp ++		dec .tokenState  = tokenArrayValue 	case  tokenObjectColon :		c , err  := dec .peek ()		if  err  != nil  {			return  err 		}		if  c  != ':'  {			return  &SyntaxError {"expected colon after object key" , dec .InputOffset ()}		}		dec .scanp ++		dec .tokenState  = tokenObjectValue 	}	return  nil }func  (dec  *Decoder ) tokenValueAllowed bool  {	switch  dec .tokenState  {	case  tokenTopValue , tokenArrayStart , tokenArrayValue , tokenObjectValue :		return  true 	}	return  false }func  (dec  *Decoder ) tokenValueEnd 	switch  dec .tokenState  {	case  tokenArrayStart , tokenArrayValue :		dec .tokenState  = tokenArrayComma 	case  tokenObjectValue :		dec .tokenState  = tokenObjectComma 	}}type  Delim  rune func  (d  Delim ) String string  {	return  string (d )}func  (dec  *Decoder ) Token Token , error ) {	for  {		c , err  := dec .peek ()		if  err  != nil  {			return  nil , err 		}		switch  c  {		case  '[' :			if  !dec .tokenValueAllowed () {				return  dec .tokenError (c )			}			dec .scanp ++			dec .tokenStack  = append (dec .tokenStack , dec .tokenState )			dec .tokenState  = tokenArrayStart 			return  Delim ('[' ), nil 		case  ']' :			if  dec .tokenState  != tokenArrayStart  && dec .tokenState  != tokenArrayComma  {				return  dec .tokenError (c )			}			dec .scanp ++			dec .tokenState  = dec .tokenStack [len (dec .tokenStack )-1 ]			dec .tokenStack  = dec .tokenStack [:len (dec .tokenStack )-1 ]			dec .tokenValueEnd ()			return  Delim (']' ), nil 		case  '{' :			if  !dec .tokenValueAllowed () {				return  dec .tokenError (c )			}			dec .scanp ++			dec .tokenStack  = append (dec .tokenStack , dec .tokenState )			dec .tokenState  = tokenObjectStart 			return  Delim ('{' ), nil 		case  '}' :			if  dec .tokenState  != tokenObjectStart  && dec .tokenState  != tokenObjectComma  {				return  dec .tokenError (c )			}			dec .scanp ++			dec .tokenState  = dec .tokenStack [len (dec .tokenStack )-1 ]			dec .tokenStack  = dec .tokenStack [:len (dec .tokenStack )-1 ]			dec .tokenValueEnd ()			return  Delim ('}' ), nil 		case  ':' :			if  dec .tokenState  != tokenObjectColon  {				return  dec .tokenError (c )			}			dec .scanp ++			dec .tokenState  = tokenObjectValue 			continue 		case  ',' :			if  dec .tokenState  == tokenArrayComma  {				dec .scanp ++				dec .tokenState  = tokenArrayValue 				continue 			}			if  dec .tokenState  == tokenObjectComma  {				dec .scanp ++				dec .tokenState  = tokenObjectKey 				continue 			}			return  dec .tokenError (c )		case  '"' :			if  dec .tokenState  == tokenObjectStart  || dec .tokenState  == tokenObjectKey  {				var  x  string 				old  := dec .tokenState 				dec .tokenState  = tokenTopValue 				err  := dec .Decode (&x )				dec .tokenState  = old 				if  err  != nil  {					return  nil , err 				}				dec .tokenState  = tokenObjectColon 				return  x , nil 			}			fallthrough 		default :			if  !dec .tokenValueAllowed () {				return  dec .tokenError (c )			}			var  x  any 			if  err  := dec .Decode (&x ); err  != nil  {				return  nil , err 			}			return  x , nil 		}	}}func  (dec  *Decoder ) tokenError c  byte ) (Token , error ) {	var  context  string 	switch  dec .tokenState  {	case  tokenTopValue :		context  = " looking for beginning of value" 	case  tokenArrayStart , tokenArrayValue , tokenObjectValue :		context  = " looking for beginning of value" 	case  tokenArrayComma :		context  = " after array element" 	case  tokenObjectKey :		context  = " looking for beginning of object key string" 	case  tokenObjectColon :		context  = " after object key" 	case  tokenObjectComma :		context  = " after object key:value pair" 	}	return  nil , &SyntaxError {"invalid character "  + quoteChar (c ) + context , dec .InputOffset ()}}func  (dec  *Decoder ) More bool  {	c , err  := dec .peek ()	return  err  == nil  && c  != ']'  && c  != '}' }func  (dec  *Decoder ) peek byte , error ) {	var  err  error 	for  {		for  i  := dec .scanp ; i  < len (dec .buf ); i ++ {			c  := dec .buf [i ]			if  isSpace (c ) {				continue 			}			dec .scanp  = i 			return  c , nil 		}				if  err  != nil  {			return  0 , err 		}		err  = dec .refill ()	}}func  (dec  *Decoder ) InputOffset int64  {	return  dec .scanned  + int64 (dec .scanp )} The pages are generated with Golds v0.6.7 . (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 @Go100and1  (reachable from the left QR code) to get the latest news of Golds .