github.com/gitbundle/modules@v0.0.0-20231025071548-85b91c5c3b01/json/json.go (about)

     1  // Copyright 2023 The GitBundle Inc. All rights reserved.
     2  // Copyright 2017 The Gitea Authors. All rights reserved.
     3  // Use of this source code is governed by a MIT-style
     4  // license that can be found in the LICENSE file.
     5  
     6  // Copyright 2020 The GitBundle Authors. All rights reserved.
     7  // Use of this source code is governed by a BSD-style
     8  // license that can be found in the LICENSE file.
     9  
    10  package json
    11  
    12  // Allow "encoding/json" import.
    13  import (
    14  	"bytes"
    15  	"encoding/binary"
    16  	"encoding/json" //nolint:depguard
    17  	"io"
    18  
    19  	jsoniter "github.com/json-iterator/go"
    20  )
    21  
    22  // Encoder represents an encoder for json
    23  type Encoder interface {
    24  	Encode(v interface{}) error
    25  }
    26  
    27  // Decoder represents a decoder for json
    28  type Decoder interface {
    29  	Decode(v interface{}) error
    30  }
    31  
    32  // Interface represents an interface to handle json data
    33  type Interface interface {
    34  	Marshal(v interface{}) ([]byte, error)
    35  	Unmarshal(data []byte, v interface{}) error
    36  	NewEncoder(writer io.Writer) Encoder
    37  	NewDecoder(reader io.Reader) Decoder
    38  	Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error
    39  }
    40  
    41  var (
    42  	// DefaultJSONHandler default json handler
    43  	DefaultJSONHandler Interface = JSONiter{jsoniter.ConfigCompatibleWithStandardLibrary}
    44  
    45  	_ Interface = StdJSON{}
    46  	_ Interface = JSONiter{}
    47  )
    48  
    49  // StdJSON implements Interface via encoding/json
    50  type StdJSON struct{}
    51  
    52  // Marshal implements Interface
    53  func (StdJSON) Marshal(v interface{}) ([]byte, error) {
    54  	return json.Marshal(v)
    55  }
    56  
    57  // Unmarshal implements Interface
    58  func (StdJSON) Unmarshal(data []byte, v interface{}) error {
    59  	return json.Unmarshal(data, v)
    60  }
    61  
    62  // NewEncoder implements Interface
    63  func (StdJSON) NewEncoder(writer io.Writer) Encoder {
    64  	return json.NewEncoder(writer)
    65  }
    66  
    67  // NewDecoder implements Interface
    68  func (StdJSON) NewDecoder(reader io.Reader) Decoder {
    69  	return json.NewDecoder(reader)
    70  }
    71  
    72  // Indent implements Interface
    73  func (StdJSON) Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error {
    74  	return json.Indent(dst, src, prefix, indent)
    75  }
    76  
    77  // JSONiter implements Interface via jsoniter
    78  type JSONiter struct {
    79  	jsoniter.API
    80  }
    81  
    82  // Marshal implements Interface
    83  func (j JSONiter) Marshal(v interface{}) ([]byte, error) {
    84  	return j.API.Marshal(v)
    85  }
    86  
    87  // Unmarshal implements Interface
    88  func (j JSONiter) Unmarshal(data []byte, v interface{}) error {
    89  	return j.API.Unmarshal(data, v)
    90  }
    91  
    92  // NewEncoder implements Interface
    93  func (j JSONiter) NewEncoder(writer io.Writer) Encoder {
    94  	return j.API.NewEncoder(writer)
    95  }
    96  
    97  // NewDecoder implements Interface
    98  func (j JSONiter) NewDecoder(reader io.Reader) Decoder {
    99  	return j.API.NewDecoder(reader)
   100  }
   101  
   102  // Indent implements Interface, since jsoniter don't support Indent, just use encoding/json's
   103  func (j JSONiter) Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error {
   104  	return json.Indent(dst, src, prefix, indent)
   105  }
   106  
   107  // Marshal converts object as bytes
   108  func Marshal(v interface{}) ([]byte, error) {
   109  	return DefaultJSONHandler.Marshal(v)
   110  }
   111  
   112  // Unmarshal decodes object from bytes
   113  func Unmarshal(data []byte, v interface{}) error {
   114  	return DefaultJSONHandler.Unmarshal(data, v)
   115  }
   116  
   117  // NewEncoder creates an encoder to write objects to writer
   118  func NewEncoder(writer io.Writer) Encoder {
   119  	return DefaultJSONHandler.NewEncoder(writer)
   120  }
   121  
   122  // NewDecoder creates a decoder to read objects from reader
   123  func NewDecoder(reader io.Reader) Decoder {
   124  	return DefaultJSONHandler.NewDecoder(reader)
   125  }
   126  
   127  // Indent appends to dst an indented form of the JSON-encoded src.
   128  func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error {
   129  	return DefaultJSONHandler.Indent(dst, src, prefix, indent)
   130  }
   131  
   132  // MarshalIndent copied from encoding/json
   133  func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) {
   134  	b, err := Marshal(v)
   135  	if err != nil {
   136  		return nil, err
   137  	}
   138  	var buf bytes.Buffer
   139  	err = Indent(&buf, b, prefix, indent)
   140  	if err != nil {
   141  		return nil, err
   142  	}
   143  	return buf.Bytes(), nil
   144  }
   145  
   146  // Valid proxy to json.Valid
   147  func Valid(data []byte) bool {
   148  	return json.Valid(data)
   149  }
   150  
   151  // UnmarshalHandleDoubleEncode - due to a bug in xorm (see https://gitea.com/xorm/xorm/pulls/1957) - it's
   152  // possible that a Blob may be double encoded or gain an unwanted prefix of 0xff 0xfe.
   153  func UnmarshalHandleDoubleEncode(bs []byte, v interface{}) error {
   154  	err := json.Unmarshal(bs, v)
   155  	if err != nil {
   156  		ok := true
   157  		rs := []byte{}
   158  		temp := make([]byte, 2)
   159  		for _, rn := range string(bs) {
   160  			if rn > 0xffff {
   161  				ok = false
   162  				break
   163  			}
   164  			binary.LittleEndian.PutUint16(temp, uint16(rn))
   165  			rs = append(rs, temp...)
   166  		}
   167  		if ok {
   168  			if len(rs) > 1 && rs[0] == 0xff && rs[1] == 0xfe {
   169  				rs = rs[2:]
   170  			}
   171  			err = json.Unmarshal(rs, v)
   172  		}
   173  	}
   174  	if err != nil && len(bs) > 2 && bs[0] == 0xff && bs[1] == 0xfe {
   175  		err = json.Unmarshal(bs[2:], v)
   176  	}
   177  	return err
   178  }