| | |
| | |
| | |
| |
|
| | |
| |
|
| | package json |
| |
|
| | import ( |
| | "errors" |
| | "io" |
| | "strings" |
| |
|
| | "encoding/json/internal" |
| | "encoding/json/internal/jsonflags" |
| | "encoding/json/jsontext" |
| | ) |
| |
|
| | |
| | var export = jsontext.Internal.Export(&internal.AllowInternalUse) |
| |
|
| | |
| | func Valid(data []byte) bool { |
| | return checkValid(data) == nil |
| | } |
| |
|
| | func checkValid(data []byte) error { |
| | d := export.GetBufferedDecoder(data) |
| | defer export.PutBufferedDecoder(d) |
| | xd := export.Decoder(d) |
| | xd.Struct.Flags.Set(jsonflags.AllowDuplicateNames | jsonflags.AllowInvalidUTF8 | 1) |
| | if _, err := d.ReadValue(); err != nil { |
| | if err == io.EOF { |
| | offset := d.InputOffset() + int64(len(d.UnreadBuffer())) |
| | err = &jsontext.SyntacticError{ByteOffset: offset, Err: io.ErrUnexpectedEOF} |
| | } |
| | return transformSyntacticError(err) |
| | } |
| | if err := xd.CheckEOF(); err != nil { |
| | return transformSyntacticError(err) |
| | } |
| | return nil |
| | } |
| |
|
| | |
| | |
| | type SyntaxError struct { |
| | msg string |
| | Offset int64 |
| | } |
| |
|
| | func (e *SyntaxError) Error() string { return e.msg } |
| |
|
| | var errUnexpectedEnd = errors.New("unexpected end of JSON input") |
| |
|
| | func transformSyntacticError(err error) error { |
| | switch serr, ok := err.(*jsontext.SyntacticError); { |
| | case serr != nil: |
| | if serr.Err == io.ErrUnexpectedEOF { |
| | serr.Err = errUnexpectedEnd |
| | } |
| | msg := serr.Err.Error() |
| | if i := strings.Index(msg, " (expecting"); i >= 0 && !strings.Contains(msg, " in literal") { |
| | msg = msg[:i] |
| | } |
| | return &SyntaxError{Offset: serr.ByteOffset, msg: syntaxErrorReplacer.Replace(msg)} |
| | case ok: |
| | return (*SyntaxError)(nil) |
| | case export.IsIOError(err): |
| | return errors.Unwrap(err) |
| | default: |
| | return err |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | var syntaxErrorReplacer = strings.NewReplacer( |
| | "object name", "object key", |
| | "at start of value", "looking for beginning of value", |
| | "at start of string", "looking for beginning of object key string", |
| | "after object value", "after object key:value pair", |
| | "in number", "in numeric literal", |
| | ) |
| |
|