1
2
3
4
5
6
7 package json
8
9 import (
10 "errors"
11 "io"
12 "strings"
13
14 "encoding/json/internal"
15 "encoding/json/internal/jsonflags"
16 "encoding/json/jsontext"
17 )
18
19
20 var export = jsontext.Internal.Export(&internal.AllowInternalUse)
21
22
23 func Valid(data []byte) bool {
24 return checkValid(data) == nil
25 }
26
27 func checkValid(data []byte) error {
28 d := export.GetBufferedDecoder(data)
29 defer export.PutBufferedDecoder(d)
30 xd := export.Decoder(d)
31 xd.Struct.Flags.Set(jsonflags.AllowDuplicateNames | jsonflags.AllowInvalidUTF8 | 1)
32 if _, err := d.ReadValue(); err != nil {
33 if err == io.EOF {
34 offset := d.InputOffset() + int64(len(d.UnreadBuffer()))
35 err = &jsontext.SyntacticError{ByteOffset: offset, Err: io.ErrUnexpectedEOF}
36 }
37 return transformSyntacticError(err)
38 }
39 if err := xd.CheckEOF(); err != nil {
40 return transformSyntacticError(err)
41 }
42 return nil
43 }
44
45
46
47 type SyntaxError struct {
48 msg string
49 Offset int64
50 }
51
52 func (e *SyntaxError) Error() string { return e.msg }
53
54 var errUnexpectedEnd = errors.New("unexpected end of JSON input")
55
56 func transformSyntacticError(err error) error {
57 switch serr, ok := err.(*jsontext.SyntacticError); {
58 case serr != nil:
59 if serr.Err == io.ErrUnexpectedEOF {
60 serr.Err = errUnexpectedEnd
61 }
62 msg := serr.Err.Error()
63 if i := strings.Index(msg, " (expecting"); i >= 0 && !strings.Contains(msg, " in literal") {
64 msg = msg[:i]
65 }
66 return &SyntaxError{Offset: serr.ByteOffset, msg: syntaxErrorReplacer.Replace(msg)}
67 case ok:
68 return (*SyntaxError)(nil)
69 case export.IsIOError(err):
70 return errors.Unwrap(err)
71 default:
72 return err
73 }
74 }
75
76
77
78
79
80 var syntaxErrorReplacer = strings.NewReplacer(
81 "object name", "object key",
82 "at start of value", "looking for beginning of value",
83 "at start of string", "looking for beginning of object key string",
84 "after object value", "after object key:value pair",
85 "in number", "in numeric literal",
86 )
87
View as plain text