123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- // Copyright 2020 The Gitea Authors. All rights reserved.
- // SPDX-License-Identifier: MIT
-
- package json
-
- // Allow "encoding/json" import.
- import (
- "bytes"
- "encoding/binary"
- "encoding/json" //nolint:depguard
- "io"
-
- jsoniter "github.com/json-iterator/go"
- )
-
- // Encoder represents an encoder for json
- type Encoder interface {
- Encode(v any) error
- }
-
- // Decoder represents a decoder for json
- type Decoder interface {
- Decode(v any) error
- }
-
- // Interface represents an interface to handle json data
- type Interface interface {
- Marshal(v any) ([]byte, error)
- Unmarshal(data []byte, v any) error
- NewEncoder(writer io.Writer) Encoder
- NewDecoder(reader io.Reader) Decoder
- Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error
- }
-
- var (
- // DefaultJSONHandler default json handler
- DefaultJSONHandler Interface = JSONiter{jsoniter.ConfigCompatibleWithStandardLibrary}
-
- _ Interface = StdJSON{}
- _ Interface = JSONiter{}
- )
-
- // StdJSON implements Interface via encoding/json
- type StdJSON struct{}
-
- // Marshal implements Interface
- func (StdJSON) Marshal(v any) ([]byte, error) {
- return json.Marshal(v)
- }
-
- // Unmarshal implements Interface
- func (StdJSON) Unmarshal(data []byte, v any) error {
- return json.Unmarshal(data, v)
- }
-
- // NewEncoder implements Interface
- func (StdJSON) NewEncoder(writer io.Writer) Encoder {
- return json.NewEncoder(writer)
- }
-
- // NewDecoder implements Interface
- func (StdJSON) NewDecoder(reader io.Reader) Decoder {
- return json.NewDecoder(reader)
- }
-
- // Indent implements Interface
- func (StdJSON) Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error {
- return json.Indent(dst, src, prefix, indent)
- }
-
- // JSONiter implements Interface via jsoniter
- type JSONiter struct {
- jsoniter.API
- }
-
- // Marshal implements Interface
- func (j JSONiter) Marshal(v any) ([]byte, error) {
- return j.API.Marshal(v)
- }
-
- // Unmarshal implements Interface
- func (j JSONiter) Unmarshal(data []byte, v any) error {
- return j.API.Unmarshal(data, v)
- }
-
- // NewEncoder implements Interface
- func (j JSONiter) NewEncoder(writer io.Writer) Encoder {
- return j.API.NewEncoder(writer)
- }
-
- // NewDecoder implements Interface
- func (j JSONiter) NewDecoder(reader io.Reader) Decoder {
- return j.API.NewDecoder(reader)
- }
-
- // Indent implements Interface, since jsoniter don't support Indent, just use encoding/json's
- func (j JSONiter) Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error {
- return json.Indent(dst, src, prefix, indent)
- }
-
- // Marshal converts object as bytes
- func Marshal(v any) ([]byte, error) {
- return DefaultJSONHandler.Marshal(v)
- }
-
- // Unmarshal decodes object from bytes
- func Unmarshal(data []byte, v any) error {
- return DefaultJSONHandler.Unmarshal(data, v)
- }
-
- // NewEncoder creates an encoder to write objects to writer
- func NewEncoder(writer io.Writer) Encoder {
- return DefaultJSONHandler.NewEncoder(writer)
- }
-
- // NewDecoder creates a decoder to read objects from reader
- func NewDecoder(reader io.Reader) Decoder {
- return DefaultJSONHandler.NewDecoder(reader)
- }
-
- // Indent appends to dst an indented form of the JSON-encoded src.
- func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error {
- return DefaultJSONHandler.Indent(dst, src, prefix, indent)
- }
-
- // MarshalIndent copied from encoding/json
- func MarshalIndent(v any, prefix, indent string) ([]byte, error) {
- b, err := Marshal(v)
- if err != nil {
- return nil, err
- }
- var buf bytes.Buffer
- err = Indent(&buf, b, prefix, indent)
- if err != nil {
- return nil, err
- }
- return buf.Bytes(), nil
- }
-
- // Valid proxy to json.Valid
- func Valid(data []byte) bool {
- return json.Valid(data)
- }
-
- // UnmarshalHandleDoubleEncode - due to a bug in xorm (see https://gitea.com/xorm/xorm/pulls/1957) - it's
- // possible that a Blob may be double encoded or gain an unwanted prefix of 0xff 0xfe.
- func UnmarshalHandleDoubleEncode(bs []byte, v any) error {
- err := json.Unmarshal(bs, v)
- if err != nil {
- ok := true
- rs := []byte{}
- temp := make([]byte, 2)
- for _, rn := range string(bs) {
- if rn > 0xffff {
- ok = false
- break
- }
- binary.LittleEndian.PutUint16(temp, uint16(rn))
- rs = append(rs, temp...)
- }
- if ok {
- if len(rs) > 1 && rs[0] == 0xff && rs[1] == 0xfe {
- rs = rs[2:]
- }
- err = json.Unmarshal(rs, v)
- }
- }
- if err != nil && len(bs) > 2 && bs[0] == 0xff && bs[1] == 0xfe {
- err = json.Unmarshal(bs[2:], v)
- }
- return err
- }
|