172 lines · 4.3 KB · Go
RawDownload
// 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 jsontype Encoder interface {	Encode(v any) error} // Decoder represents a decoder for jsontype Decoder interface {	Decode(v any) error} // Interface represents an interface to handle json datatype 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/jsontype StdJSON struct{} // Marshal implements Interfacefunc (StdJSON) Marshal(v any) ([]byte, error) {	return json.Marshal(v)} // Unmarshal implements Interfacefunc (StdJSON) Unmarshal(data []byte, v any) error {	return json.Unmarshal(data, v)} // NewEncoder implements Interfacefunc (StdJSON) NewEncoder(writer io.Writer) Encoder {	return json.NewEncoder(writer)} // NewDecoder implements Interfacefunc (StdJSON) NewDecoder(reader io.Reader) Decoder {	return json.NewDecoder(reader)} // Indent implements Interfacefunc (StdJSON) Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error {	return json.Indent(dst, src, prefix, indent)} // JSONiter implements Interface via jsonitertype JSONiter struct {	jsoniter.API} // Marshal implements Interfacefunc (j JSONiter) Marshal(v any) ([]byte, error) {	return j.API.Marshal(v)} // Unmarshal implements Interfacefunc (j JSONiter) Unmarshal(data []byte, v any) error {	return j.API.Unmarshal(data, v)} // NewEncoder implements Interfacefunc (j JSONiter) NewEncoder(writer io.Writer) Encoder {	return j.API.NewEncoder(writer)} // NewDecoder implements Interfacefunc (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'sfunc (j JSONiter) Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error {	return json.Indent(dst, src, prefix, indent)} // Marshal converts object as bytesfunc Marshal(v any) ([]byte, error) {	return DefaultJSONHandler.Marshal(v)} // Unmarshal decodes object from bytesfunc Unmarshal(data []byte, v any) error {	return DefaultJSONHandler.Unmarshal(data, v)} // NewEncoder creates an encoder to write objects to writerfunc NewEncoder(writer io.Writer) Encoder {	return DefaultJSONHandler.NewEncoder(writer)} // NewDecoder creates a decoder to read objects from readerfunc 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/jsonfunc 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.Validfunc 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}