mirror of
https://gh-proxy.org/https://github.com/klinsmaya/new-api.git
synced 2026-11-09 01:47:07 +08:00
`common/json.go` and `relaykit/relayconvert/kitutil/json.go` were two hard-wired copies of the same encoding/json wrapper, so swapping the JSON engine required editing both modules. - kitutil defines a `Codec` interface with a standard-library default and a `SetCodec` hook, mirroring the existing SetLogging host hook; every kitutil JSON helper and relaykit DTO (un)marshal method goes through it - `common/json.go` forwards to kitutil and injects `hostJSONCodec` from init() so tests run on the same engine as production; swapping the engine now touches only this type in the root module - route the remaining direct encoding/json calls inside relaykit (dto/values.go, responses stream validation) through kitutil - add a codec routing test and a host codec conformance test locking the encoding semantics the DTOs depend on Direct encoding/json call sites in the root module are left for a separate cleanup.
84 lines
2.2 KiB
Go
84 lines
2.2 KiB
Go
package common
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"io"
|
|
|
|
kitutil "github.com/QuantumNous/new-api/relaykit/relayconvert/kitutil"
|
|
"github.com/gin-gonic/gin/binding"
|
|
)
|
|
|
|
// hostJSONCodec is the single place where the host chooses its JSON engine.
|
|
// Swap the implementation here (for example to sonic.ConfigStd) and every
|
|
// common.* and kitutil.* JSON helper, including relaykit DTO (un)marshalling,
|
|
// follows. Injected from init() rather than main() so tests run on the same
|
|
// engine as production: common is imported by virtually every root package
|
|
// and test binary, while main() never executes under `go test`.
|
|
type hostJSONCodec struct{}
|
|
|
|
func (hostJSONCodec) Marshal(v any) ([]byte, error) {
|
|
return json.Marshal(v)
|
|
}
|
|
|
|
func (hostJSONCodec) Unmarshal(data []byte, v any) error {
|
|
return json.Unmarshal(data, v)
|
|
}
|
|
|
|
func (hostJSONCodec) Decode(r io.Reader, v any) error {
|
|
return json.NewDecoder(r).Decode(v)
|
|
}
|
|
|
|
func (hostJSONCodec) Valid(data []byte) bool {
|
|
return json.Valid(data)
|
|
}
|
|
|
|
func init() {
|
|
kitutil.SetCodec(hostJSONCodec{})
|
|
}
|
|
|
|
func Unmarshal(data []byte, v any) error {
|
|
return kitutil.Unmarshal(data, v)
|
|
}
|
|
|
|
func UnmarshalJsonStr(data string, v any) error {
|
|
return kitutil.UnmarshalJsonStr(data, v)
|
|
}
|
|
|
|
func DecodeJson(reader io.Reader, v any) error {
|
|
return kitutil.DecodeJson(reader, v)
|
|
}
|
|
|
|
// DecodeJsonWithValidation decodes JSON and applies Gin's configured binding-tag
|
|
// validator, including binding:"required" and any registered custom validators.
|
|
func DecodeJsonWithValidation(reader io.Reader, v any) error {
|
|
if err := DecodeJson(reader, v); err != nil {
|
|
return err
|
|
}
|
|
if binding.Validator == nil {
|
|
return nil
|
|
}
|
|
return binding.Validator.ValidateStruct(v)
|
|
}
|
|
|
|
func Marshal(v any) ([]byte, error) {
|
|
return kitutil.Marshal(v)
|
|
}
|
|
|
|
func IndentJson(data []byte) ([]byte, error) {
|
|
var buffer bytes.Buffer
|
|
if err := json.Indent(&buffer, data, "", " "); err != nil {
|
|
return nil, err
|
|
}
|
|
return buffer.Bytes(), nil
|
|
}
|
|
|
|
func GetJsonType(data json.RawMessage) string {
|
|
return kitutil.GetJsonType(data)
|
|
}
|
|
|
|
// JsonRawMessageToString returns JSON strings as their decoded value and other JSON values as raw text.
|
|
func JsonRawMessageToString(data json.RawMessage) string {
|
|
return kitutil.JsonRawMessageToString(data)
|
|
}
|