From 879606d0efb8eb8544161a3a4a011cc2afb59706 Mon Sep 17 00:00:00 2001 From: AI Engineer Date: Thu, 14 May 2026 15:32:10 +0800 Subject: [PATCH] fix(cast): JSON tag '-' handling consistency --- CHANGELOG-LATEST.md | 4 - CODE-SUMMARY.md | 286 -------------------------------------------- json_decoder.go | 5 +- json_encoder.go | 5 +- 4 files changed, 8 insertions(+), 292 deletions(-) delete mode 100644 CHANGELOG-LATEST.md delete mode 100644 CODE-SUMMARY.md diff --git a/CHANGELOG-LATEST.md b/CHANGELOG-LATEST.md deleted file mode 100644 index 1498182..0000000 --- a/CHANGELOG-LATEST.md +++ /dev/null @@ -1,4 +0,0 @@ -## [v1.2.9] - 2026-05-09 -### Changed -- **移除第三方依赖**: 移除了对 `jsontag` 模块的依赖,统一使用标准库及自有基础设施对齐,增强了模块的独立性与长期稳定性。 - diff --git a/CODE-SUMMARY.md b/CODE-SUMMARY.md deleted file mode 100644 index 01e20aa..0000000 --- a/CODE-SUMMARY.md +++ /dev/null @@ -1,286 +0,0 @@ -### cast > cast.go -```go - - - -// If 泛型三元表达式 -func If[T any](condition bool, trueVal, falseVal T) T - - -// In 泛型包含判断 -func In[T comparable](arr []T, val T) bool - - -// As 忽略错误,返回零值 (消除摩擦) -func As[T any](v T, err error) T - - -func RealValue(v reflect.Value) reflect.Value - - -// --- Core Cast Logic --- - -var ( - timeType = reflect.TypeOf(time.Time{}) -) - -// To 深度转换 (支持基础类型、Slice、Map、Struct 及 JSON 自动转换,零摩擦模式) -func To[T any](v any) T - - -// Convert 深度转换 (支持基础类型、Slice、Map、Struct 及 JSON 自动转换,原地更新) -func Convert(dst, src any) - - -func performRecursiveTo(src, dst reflect.Value) - - -// 内部递归助手 (零分配/高性能设计) - -func recursiveMapToStruct(src, dst reflect.Value) - - -func recursiveStructToStruct(src, dst reflect.Value) - - -func recursiveMapToMap(src, dst reflect.Value) - - -func recursiveStructToMap(src, dst reflect.Value) - - -func recursiveSliceToMap(src, dst reflect.Value) - - -func recursiveSliceToSlice(src, dst reflect.Value) - - -func ToTime(v any, format string) time.Time - - -func reflectCast(value any, t reflect.Type) reflect.Value - - -func reflectCastE(value any, t reflect.Type) (reflect.Value, error) - - -func ToInt64E(v any) (int64, error) - - -func ToUint64E(v any) (uint64, error) - - -func ToFloat64E(v any) (float64, error) - - -func isJSONText(v any) bool -``` - -### cast > time.go -```go - - - -// TimeZone 定义了特定时区上下文下的时间操作 -type TimeZone struct { - loc *time.Location -} - -// NewTimeZone 创建一个时区上下文 -func NewTimeZone(loc *time.Location) *TimeZone - - -// DefaultTimeZone 全局默认时区,默认为本地时区 -var DefaultTimeZone = NewTimeZone(time.Local) - -// SetDefaultTimeZone 修改全局默认时区 -func SetDefaultTimeZone(loc *time.Location) - - -// 在包级别预先初始化 Replacer,0 额外分配 -var timeFormatReplacer = strings.NewReplacer( - "YYYY", "2006", "YY", "06", - "MM", "01", "M", "1", - "DD", "02", "D", "2", - "HH", "15", "hh", "03", "h", "3", - "mm", "04", "ss", "05", - "a", "pm", "A", "PM", - "ZZ", "-0700", "Z", "-07:00", -) - -// ParseTime 将任意类型转换为 time.Time。 -// 支持:time.Time, 时间戳 (秒/毫秒/微秒/纳秒), RFC3339, JS 格式, 中文格式等。 -// 转换失败返回零值 time.Time{} 以保持 cast 的静默风格。 -func (tz *TimeZone) ParseTime(v any) time.Time - - -var cnDateRegex = regexp.MustCompile(`(\d{2,4})?年?(\d{1,2})月(\d{1,2})日`) -var cnTimeRegex = regexp.MustCompile(`(上午|下午)?(\d{1,2})(?:时|点|:)(\d{1,2})(?:分|:)(\d{1,2})?秒?`) - -func (tz *TimeZone) parseCN(str string) time.Time - - -// ParseTime 将任意类型转换为 time.Time。 -func ParseTime(v any) time.Time - - -// FormatTime 格式化时间。 -// layout 支持: YYYY-MM-DD HH:mm:ss, YYYY/MM/DD, HH:mm 等直观格式。 -func (tz *TimeZone) FormatTime(layout string, v any) string - - -// FormatTime 格式化时间。 -func FormatTime(layout string, v any) string - - -// AddTime 时间加减 DSL。 -// 格式如: "+1Y-2M+3D", "+1h30m", "-1s"。 -// 单位支持: Y (年), M (月), D (天), h, m, s, ms, us, ns。 -func (tz *TimeZone) AddTime(expr string, v any) time.Time - - -// AddTime 时间加减 DSL。 -func AddTime(expr string, v any) time.Time - - -// Now 获取当前时间 -func (tz *TimeZone) Now() time.Time - - -// Location 获取当前时区 -func (tz *TimeZone) Location() *time.Location - - -// Now 获取当前时间 -func Now() time.Time - - -// DescribeDuration 将时长转化为自然语言描述,例如 "1h 1m 1s" -func (tz *TimeZone) DescribeDuration(d time.Duration) string - - -// DescribeDuration 将时长转化为自然语言描述 -func DescribeDuration(d time.Duration) string - -``` - -### cast > json_encoder.go -```go - - - -var ( - bufferPool = sync.Pool{ - New: func() any { - return new(bytes.Buffer) - }, - } - encoderStructCache sync.Map -) - -type encoderFieldDescriptor struct { - index int - name string - isAnonymous bool - isTime bool - timeFormat string - keepKey bool -} - -type encoderStructDescriptor struct { - fields []encoderFieldDescriptor -} - -type fastEncoder struct { - buffer *bytes.Buffer - desensitizeKeys map[string]bool -} - -func (encoder *fastEncoder) encode(value any) error - - -func (encoder *fastEncoder) encodeValue(reflectValue reflect.Value, path string) error - - -func (encoder *fastEncoder) writeTime(t time.Time, format string) - - -func (encoder *fastEncoder) encodeSlice(reflectValue reflect.Value, path string) error - - -func (encoder *fastEncoder) encodeMap(reflectValue reflect.Value, path string) error - - -func getEncoderStructDescriptor(reflectType reflect.Type) *encoderStructDescriptor - - -func (encoder *fastEncoder) encodeStruct(reflectValue reflect.Value, path string) error - - -func (encoder *fastEncoder) encodeStructFields(reflectValue reflect.Value, path string, first *bool) error - - -func (encoder *fastEncoder) writeString(str string) - - -// 导出函数 -func fastToJSONBytes(value any, desensitizeKeys ...string) ([]byte, error) - -``` - -### cast > json_decoder.go -```go - - - -var ( - structFieldMapCache sync.Map -) - -type decoderFieldDescriptor struct { - index int - isTime bool - timeFormat string - normalized string -} - -type decoderStructDescriptor struct { - exactMatches map[string]decoderFieldDescriptor - fields []decoderFieldDescriptor -} - -type decoder struct { - data []byte - pos int -} - -func (d *decoder) skipWhitespace() - - -func (d *decoder) decode(value any) error - - -func (d *decoder) decodeValue(reflectValue reflect.Value, timeFormat string) error - - -func (d *decoder) skipValue() error - - -// Frictionless Logic - -func getDecoderFieldMap(reflectType reflect.Type) *decoderStructDescriptor - - -func matchField(key string, descriptor *decoderStructDescriptor) (int, bool, string, bool) - - -func normalizeEqual(raw string, normalized string) bool - - -func normalizeKey(str string) string - - -func fastUnmarshalJSONBytes(data []byte, value any) error - -``` - diff --git a/json_decoder.go b/json_decoder.go index b2f0d29..1c576b3 100644 --- a/json_decoder.go +++ b/json_decoder.go @@ -445,7 +445,10 @@ func getDecoderFieldMap(reflectType reflect.Type) *decoderStructDescriptor { // 1. Tag tag := field.Tag.Get("json") - if tag != "" && tag != "-" { + if tag == "-" { + continue + } + if tag != "" { parts := strings.Split(tag, ",") tagName := parts[0] for _, part := range parts { diff --git a/json_encoder.go b/json_encoder.go index 1b49383..2496468 100644 --- a/json_encoder.go +++ b/json_encoder.go @@ -217,9 +217,12 @@ func getEncoderStructDescriptor(reflectType reflect.Type) *encoderStructDescript } tag := field.Tag.Get("json") + if tag == "-" { + continue + } fieldDesc.keepKey = strings.Contains(string(field.Tag), "keepKey") - if tag != "" && tag != "-" { + if tag != "" { parts := strings.Split(tag, ",") for _, part := range parts { if strings.HasPrefix(part, "format=") {