api.go 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. /*
  2. * Copyright 2021 ByteDance Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package sonic
  17. import (
  18. `io`
  19. `github.com/bytedance/sonic/ast`
  20. `github.com/bytedance/sonic/internal/rt`
  21. )
  22. const (
  23. // UseStdJSON indicates you are using fallback implementation (encoding/json)
  24. UseStdJSON = iota
  25. // UseSonicJSON indicates you are using real sonic implementation
  26. UseSonicJSON
  27. )
  28. // APIKind is the kind of API, 0 is std json, 1 is sonic.
  29. const APIKind = apiKind
  30. // Config is a combination of sonic/encoder.Options and sonic/decoder.Options
  31. type Config struct {
  32. // EscapeHTML indicates encoder to escape all HTML characters
  33. // after serializing into JSON (see https://pkg.go.dev/encoding/json#HTMLEscape).
  34. // WARNING: This hurts performance A LOT, USE WITH CARE.
  35. EscapeHTML bool
  36. // SortMapKeys indicates encoder that the keys of a map needs to be sorted
  37. // before serializing into JSON.
  38. // WARNING: This hurts performance A LOT, USE WITH CARE.
  39. SortMapKeys bool
  40. // CompactMarshaler indicates encoder that the output JSON from json.Marshaler
  41. // is always compact and needs no validation
  42. CompactMarshaler bool
  43. // NoQuoteTextMarshaler indicates encoder that the output text from encoding.TextMarshaler
  44. // is always escaped string and needs no quoting
  45. NoQuoteTextMarshaler bool
  46. // NoNullSliceOrMap indicates encoder that all empty Array or Object are encoded as '[]' or '{}',
  47. // instead of 'null'
  48. NoNullSliceOrMap bool
  49. // UseInt64 indicates decoder to unmarshal an integer into an interface{} as an
  50. // int64 instead of as a float64.
  51. UseInt64 bool
  52. // UseNumber indicates decoder to unmarshal a number into an interface{} as a
  53. // json.Number instead of as a float64.
  54. UseNumber bool
  55. // UseUnicodeErrors indicates decoder to return an error when encounter invalid
  56. // UTF-8 escape sequences.
  57. UseUnicodeErrors bool
  58. // DisallowUnknownFields indicates decoder to return an error when the destination
  59. // is a struct and the input contains object keys which do not match any
  60. // non-ignored, exported fields in the destination.
  61. DisallowUnknownFields bool
  62. // CopyString indicates decoder to decode string values by copying instead of referring.
  63. CopyString bool
  64. // ValidateString indicates decoder and encoder to validate string values: decoder will return errors
  65. // when unescaped control chars(\u0000-\u001f) in the string value of JSON.
  66. ValidateString bool
  67. // NoValidateJSONMarshaler indicates that the encoder should not validate the output string
  68. // after encoding the JSONMarshaler to JSON.
  69. NoValidateJSONMarshaler bool
  70. // NoValidateJSONSkip indicates the decoder should not validate the JSON value when skipping it,
  71. // such as unknown-fields, mismatched-type, redundant elements..
  72. NoValidateJSONSkip bool
  73. // NoEncoderNewline indicates that the encoder should not add a newline after every message
  74. NoEncoderNewline bool
  75. // Encode Infinity or Nan float into `null`, instead of returning an error.
  76. EncodeNullForInfOrNan bool
  77. }
  78. var (
  79. // ConfigDefault is the default config of APIs, aiming at efficiency and safety.
  80. ConfigDefault = Config{}.Froze()
  81. // ConfigStd is the standard config of APIs, aiming at being compatible with encoding/json.
  82. ConfigStd = Config{
  83. EscapeHTML : true,
  84. SortMapKeys: true,
  85. CompactMarshaler: true,
  86. CopyString : true,
  87. ValidateString : true,
  88. }.Froze()
  89. // ConfigFastest is the fastest config of APIs, aiming at speed.
  90. ConfigFastest = Config{
  91. NoQuoteTextMarshaler: true,
  92. NoValidateJSONMarshaler: true,
  93. NoValidateJSONSkip: true,
  94. }.Froze()
  95. )
  96. // API is a binding of specific config.
  97. // This interface is inspired by github.com/json-iterator/go,
  98. // and has same behaviors under equivalent config.
  99. type API interface {
  100. // MarshalToString returns the JSON encoding string of v
  101. MarshalToString(v interface{}) (string, error)
  102. // Marshal returns the JSON encoding bytes of v.
  103. Marshal(v interface{}) ([]byte, error)
  104. // MarshalIndent returns the JSON encoding bytes with indent and prefix.
  105. MarshalIndent(v interface{}, prefix, indent string) ([]byte, error)
  106. // UnmarshalFromString parses the JSON-encoded bytes and stores the result in the value pointed to by v.
  107. UnmarshalFromString(str string, v interface{}) error
  108. // Unmarshal parses the JSON-encoded string and stores the result in the value pointed to by v.
  109. Unmarshal(data []byte, v interface{}) error
  110. // NewEncoder create a Encoder holding writer
  111. NewEncoder(writer io.Writer) Encoder
  112. // NewDecoder create a Decoder holding reader
  113. NewDecoder(reader io.Reader) Decoder
  114. // Valid validates the JSON-encoded bytes and reports if it is valid
  115. Valid(data []byte) bool
  116. }
  117. // Encoder encodes JSON into io.Writer
  118. type Encoder interface {
  119. // Encode writes the JSON encoding of v to the stream, followed by a newline character.
  120. Encode(val interface{}) error
  121. // SetEscapeHTML specifies whether problematic HTML characters
  122. // should be escaped inside JSON quoted strings.
  123. // The default behavior NOT ESCAPE
  124. SetEscapeHTML(on bool)
  125. // SetIndent instructs the encoder to format each subsequent encoded value
  126. // as if indented by the package-level function Indent(dst, src, prefix, indent).
  127. // Calling SetIndent("", "") disables indentation
  128. SetIndent(prefix, indent string)
  129. }
  130. // Decoder decodes JSON from io.Read
  131. type Decoder interface {
  132. // Decode reads the next JSON-encoded value from its input and stores it in the value pointed to by v.
  133. Decode(val interface{}) error
  134. // Buffered returns a reader of the data remaining in the Decoder's buffer.
  135. // The reader is valid until the next call to Decode.
  136. Buffered() io.Reader
  137. // DisallowUnknownFields causes the Decoder to return an error when the destination is a struct
  138. // and the input contains object keys which do not match any non-ignored, exported fields in the destination.
  139. DisallowUnknownFields()
  140. // More reports whether there is another element in the current array or object being parsed.
  141. More() bool
  142. // UseNumber causes the Decoder to unmarshal a number into an interface{} as a Number instead of as a float64.
  143. UseNumber()
  144. }
  145. // Marshal returns the JSON encoding bytes of v.
  146. func Marshal(val interface{}) ([]byte, error) {
  147. return ConfigDefault.Marshal(val)
  148. }
  149. // MarshalIndent is like Marshal but applies Indent to format the output.
  150. // Each JSON element in the output will begin on a new line beginning with prefix
  151. // followed by one or more copies of indent according to the indentation nesting.
  152. func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) {
  153. return ConfigDefault.MarshalIndent(v, prefix, indent)
  154. }
  155. // MarshalString returns the JSON encoding string of v.
  156. func MarshalString(val interface{}) (string, error) {
  157. return ConfigDefault.MarshalToString(val)
  158. }
  159. // Unmarshal parses the JSON-encoded data and stores the result in the value pointed to by v.
  160. // NOTICE: This API copies given buffer by default,
  161. // if you want to pass JSON more efficiently, use UnmarshalString instead.
  162. func Unmarshal(buf []byte, val interface{}) error {
  163. return ConfigDefault.Unmarshal(buf, val)
  164. }
  165. // UnmarshalString is like Unmarshal, except buf is a string.
  166. func UnmarshalString(buf string, val interface{}) error {
  167. return ConfigDefault.UnmarshalFromString(buf, val)
  168. }
  169. // Get searches and locates the given path from src json,
  170. // and returns a ast.Node representing the partially json.
  171. //
  172. // Each path arg must be integer or string:
  173. // - Integer is target index(>=0), means searching current node as array.
  174. // - String is target key, means searching current node as object.
  175. //
  176. //
  177. // Notice: It expects the src json is **Well-formed** and **Immutable** when calling,
  178. // otherwise it may return unexpected result.
  179. // Considering memory safety, the returned JSON is **Copied** from the input
  180. func Get(src []byte, path ...interface{}) (ast.Node, error) {
  181. return GetCopyFromString(rt.Mem2Str(src), path...)
  182. }
  183. //GetWithOptions searches and locates the given path from src json,
  184. // with specific options of ast.Searcher
  185. func GetWithOptions(src []byte, opts ast.SearchOptions, path ...interface{}) (ast.Node, error) {
  186. s := ast.NewSearcher(rt.Mem2Str(src))
  187. s.SearchOptions = opts
  188. return s.GetByPath(path...)
  189. }
  190. // GetFromString is same with Get except src is string.
  191. //
  192. // WARNING: The returned JSON is **Referenced** from the input.
  193. // Caching or long-time holding the returned node may cause OOM.
  194. // If your src is big, consider use GetFromStringCopy().
  195. func GetFromString(src string, path ...interface{}) (ast.Node, error) {
  196. return ast.NewSearcher(src).GetByPath(path...)
  197. }
  198. // GetCopyFromString is same with Get except src is string
  199. func GetCopyFromString(src string, path ...interface{}) (ast.Node, error) {
  200. return ast.NewSearcher(src).GetByPathCopy(path...)
  201. }
  202. // Valid reports whether data is a valid JSON encoding.
  203. func Valid(data []byte) bool {
  204. return ConfigDefault.Valid(data)
  205. }
  206. // Valid reports whether data is a valid JSON encoding.
  207. func ValidString(data string) bool {
  208. return ConfigDefault.Valid(rt.Str2Mem(data))
  209. }