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 }