feat: custom json marshaling implementation, replace json and yaml library (#89)

* chore: replace gopkg.in/yaml.v3 vs goccy/go-yaml; replace encoding/json with bytedance/sonic

* fix: yaml unmarshal panic

* feat: custom json marshaler implementation

* chore: fix import and err marshal handling

---------

Co-authored-by: yusing <yusing@6uo.me>
This commit is contained in:
Yuzerion
2025-04-16 15:02:11 +08:00
committed by GitHub
parent 57292f0fe8
commit 80bc018a7f
65 changed files with 1749 additions and 205 deletions

View File

@@ -1,8 +1,9 @@
package atomic
import (
"encoding/json"
"sync/atomic"
"github.com/yusing/go-proxy/pkg/json"
)
type Value[T any] struct {
@@ -29,6 +30,6 @@ func (a *Value[T]) Swap(v T) T {
return zero
}
func (a *Value[T]) MarshalJSON() ([]byte, error) {
return json.Marshal(a.Load())
func (a *Value[T]) MarshalJSONTo(buf []byte) []byte {
return json.MarshalTo(a.Load(), buf)
}

View File

@@ -3,8 +3,8 @@ package functional
import (
"sync"
"github.com/goccy/go-yaml"
"github.com/puzpuzpuz/xsync/v3"
"gopkg.in/yaml.v3"
)
type Map[KT comparable, VT any] struct {

View File

@@ -1,7 +1,7 @@
package utils
import (
"encoding/json"
"bytes"
"errors"
"net"
"net/url"
@@ -11,11 +11,13 @@ import (
"strings"
"time"
"github.com/yusing/go-proxy/pkg/json"
"github.com/go-playground/validator/v10"
"github.com/goccy/go-yaml"
"github.com/yusing/go-proxy/internal/gperr"
"github.com/yusing/go-proxy/internal/utils/functional"
"github.com/yusing/go-proxy/internal/utils/strutils"
"gopkg.in/yaml.v3"
)
type SerializedObject = map[string]any
@@ -24,9 +26,12 @@ type (
MapMarshaler interface {
MarshalMap() map[string]any
}
MapUnmarshaller interface {
MapUnmarshaler interface {
UnmarshalMap(m map[string]any) gperr.Error
}
Marshaler interface {
MarshalJSONTo(buf *bytes.Buffer) error
}
)
var (
@@ -50,12 +55,8 @@ var (
typeURL = reflect.TypeFor[url.URL]()
typeCIDR = reflect.TypeFor[net.IPNet]()
typeMapMarshaller = reflect.TypeFor[MapMarshaler]()
typeMapUnmarshaler = reflect.TypeFor[MapUnmarshaller]()
typeJSONMarshaller = reflect.TypeFor[json.Marshaler]()
typeMapUnmarshaler = reflect.TypeFor[MapUnmarshaler]()
typeStrParser = reflect.TypeFor[strutils.Parser]()
typeAny = reflect.TypeOf((*any)(nil)).Elem()
)
var defaultValues = functional.NewMapOf[reflect.Type, func() any]()
@@ -92,14 +93,14 @@ func extractFields(t reflect.Type) (all, anonymous []reflect.StructField) {
if !field.IsExported() {
continue
}
// not checking tagJSON because json:"-" is for skipping json.Marshal
if field.Tag.Get(tagDeserialize) == "-" {
continue
}
if field.Anonymous {
f1, f2 := extractFields(field.Type)
fields = append(fields, f1...)
nested, _ := extractFields(field.Type)
fields = append(fields, nested...)
anonymous = append(anonymous, field)
anonymous = append(anonymous, f2...)
} else {
fields = append(fields, field)
}
@@ -215,7 +216,7 @@ func MapUnmarshalValidate(src SerializedObject, dst any) (err gperr.Error) {
if err != nil {
return err
}
return dstV.Addr().Interface().(MapUnmarshaller).UnmarshalMap(src)
return dstV.Addr().Interface().(MapUnmarshaler).UnmarshalMap(src)
}
dstV, dstT, err = dive(dstV)
@@ -560,7 +561,7 @@ func ConvertString(src string, dst reflect.Value) (convertible bool, convErr gpe
func UnmarshalValidateYAML[T any](data []byte, target *T) gperr.Error {
m := make(map[string]any)
if err := yaml.Unmarshal(data, m); err != nil {
if err := yaml.Unmarshal(data, &m); err != nil {
return gperr.Wrap(err)
}
return MapUnmarshalValidate(m, target)
@@ -568,7 +569,7 @@ func UnmarshalValidateYAML[T any](data []byte, target *T) gperr.Error {
func UnmarshalValidateYAMLMap[V any](data []byte) (_ functional.Map[string, V], err gperr.Error) {
m := make(map[string]any)
if err = gperr.Wrap(yaml.Unmarshal(data, m)); err != nil {
if err = gperr.Wrap(yaml.Unmarshal(data, &m)); err != nil {
return
}
m2 := make(map[string]V, len(m))

View File

@@ -8,8 +8,8 @@ import (
"strconv"
"testing"
"github.com/goccy/go-yaml"
. "github.com/yusing/go-proxy/internal/utils/testing"
"gopkg.in/yaml.v3"
)
func TestUnmarshal(t *testing.T) {