github.com/goshafaq/sonic@v0.0.0-20231026082336-871835fb94c6/api.go (about)

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