code.gitea.io/gitea@v1.19.3/modules/json/json.go (about)

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