mirror of
https://github.com/go-gitea/gitea.git
synced 2026-08-22 04:05:59 +02:00
Restore the toolchain pin renovate dropped. The go directive has to lose its patch version for that: go removes a toolchain equal to it, and every go command then refuses to run until go.mod is tidied. Go 1.27 changes the flate encoder, so the sizes and checksums pinned by package tests move with the compressed output. Hash the avatar test input directly instead of a png, which has no bearing on what it asserts. encoding/json v2 is no longer an experiment, so drop the v1 implementation and GOEXPERIMENT=jsonv2 with it. Assisted-by: Claude Code:Opus 5
97 lines
3.0 KiB
Go
97 lines
3.0 KiB
Go
// Copyright 2025 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package json
|
|
|
|
import (
|
|
"bytes"
|
|
jsonv1 "encoding/json" //nolint:depguard // this package wraps it
|
|
"encoding/json/jsontext" //nolint:depguard // this package wraps it
|
|
jsonv2 "encoding/json/v2" //nolint:depguard // this package wraps it
|
|
"io"
|
|
)
|
|
|
|
// JSONv2 implements Interface via encoding/json/v2
|
|
type JSONv2 struct {
|
|
marshalOptions jsonv2.Options
|
|
marshalKeepOptionalEmptyOptions jsonv2.Options
|
|
unmarshalOptions jsonv2.Options
|
|
unmarshalCaseInsensitiveOptions jsonv2.Options
|
|
}
|
|
|
|
var jsonV2 JSONv2
|
|
|
|
func init() {
|
|
commonMarshalOptions := []jsonv2.Options{
|
|
jsonv2.FormatNilSliceAsNull(true),
|
|
jsonv2.FormatNilMapAsNull(true),
|
|
}
|
|
jsonV2.marshalOptions = jsonv2.JoinOptions(commonMarshalOptions...)
|
|
jsonV2.unmarshalOptions = jsonv2.DefaultOptionsV2()
|
|
|
|
// By default, "json/v2" omitempty removes all `""` empty strings, no matter where it comes from.
|
|
// v1 has a different behavior: if the `""` is from a null pointer, or a Marshal function, it is kept.
|
|
// Golang issue: https://github.com/golang/go/issues/75623 encoding/json/v2: unable to make omitempty work with pointer or Optional type with goexperiment.jsonv2
|
|
jsonV2.marshalKeepOptionalEmptyOptions = jsonv2.JoinOptions(append(commonMarshalOptions, jsonv1.OmitEmptyWithLegacySemantics(true))...)
|
|
|
|
// Some legacy code uses case-insensitive matching (for example: parsing oci.ImageConfig)
|
|
jsonV2.unmarshalCaseInsensitiveOptions = jsonv2.JoinOptions(jsonv2.MatchCaseInsensitiveNames(true))
|
|
}
|
|
|
|
func getDefaultJSONHandler() Interface {
|
|
return &jsonV2
|
|
}
|
|
|
|
func MarshalKeepOptionalEmpty(v any) ([]byte, error) {
|
|
return jsonv2.Marshal(v, jsonV2.marshalKeepOptionalEmptyOptions)
|
|
}
|
|
|
|
func (j *JSONv2) Marshal(v any) ([]byte, error) {
|
|
return jsonv2.Marshal(v, j.marshalOptions)
|
|
}
|
|
|
|
func (j *JSONv2) MarshalWrite(w io.Writer, v any) error {
|
|
return jsonv2.MarshalWrite(w, v, j.marshalOptions)
|
|
}
|
|
|
|
func (j *JSONv2) Unmarshal(data []byte, v any) error {
|
|
return jsonv2.Unmarshal(data, v, j.unmarshalOptions)
|
|
}
|
|
|
|
func (j *JSONv2) NewEncoder(writer io.Writer) Encoder {
|
|
return &jsonV2Encoder{writer: writer, opts: j.marshalOptions}
|
|
}
|
|
|
|
func (j *JSONv2) NewDecoder(reader io.Reader) Decoder {
|
|
return &jsonV2Decoder{reader: reader, opts: j.unmarshalOptions}
|
|
}
|
|
|
|
// Indent implements Interface using standard library (JSON v2 doesn't have Indent yet)
|
|
func (*JSONv2) Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error {
|
|
return jsonv1.Indent(dst, src, prefix, indent)
|
|
}
|
|
|
|
type jsonV2Encoder struct {
|
|
writer io.Writer
|
|
opts jsonv2.Options
|
|
}
|
|
|
|
func (e *jsonV2Encoder) Encode(v any) error {
|
|
return jsonv2.MarshalWrite(e.writer, v, e.opts)
|
|
}
|
|
|
|
type jsonV2Decoder struct {
|
|
reader io.Reader
|
|
opts jsonv2.Options
|
|
}
|
|
|
|
func (d *jsonV2Decoder) Decode(v any) error {
|
|
return jsonv2.UnmarshalRead(d.reader, v, d.opts)
|
|
}
|
|
|
|
func NewDecoderCaseInsensitive(reader io.Reader) Decoder {
|
|
return &jsonV2Decoder{reader: reader, opts: jsonV2.unmarshalCaseInsensitiveOptions}
|
|
}
|
|
|
|
type Value = jsontext.Value
|