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 }