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