✅ 验证清单
🚀 Go 版本
1.26.1
📦 Dubbo-go 版本
v 3.3.0
🖥️ 服务端配置
No response
💻 客户端配置
No response
🌐 协议配置
No response
📋 注册中心配置
No response
💾 操作系统
🍎 macOS
📝 Bug 描述
MapGeneralizer.Generalize uses the m struct tag as the generated map key,
but MapGeneralizer.Realize does not use the same tag when decoding the map.
Realize calls mapstructure.Decode with its default configuration.
mapstructure defaults to the mapstructure tag and only performs
case-insensitive field-name matching.
As a result, an m tag that genuinely renames a field, such as
UserID -> user_id, cannot be mapped back. The key is silently ignored,
the target field remains its zero value, and no error is returned.
This affects the default generic=true map generalization mode, including
generic request arguments, generic responses, and GenericService.InvokeWithType.
🔄 重现步骤
Create filter/generic/generalizer/m_tag_repro_test.go:
package generalizer_test
import (
"reflect"
"testing"
"dubbo.apache.org/dubbo-go/v3/filter/generic/generalizer"
)
func TestMapGeneralizerMTagRoundTrip(t *testing.T) {
type Payload struct {
UserID string `m:"user_id"`
Name string
}
in := Payload{
UserID: "42",
Name: "alice",
}
g := generalizer.GetMapGeneralizer()
generalized, err := g.Generalize(in)
if err != nil {
t.Fatal(err)
}
t.Logf("generalized: %#v", generalized)
realized, err := g.Realize(generalized, reflect.TypeOf(in))
if err != nil {
t.Fatal(err)
}
got := realized.(Payload)
t.Logf("realized: %#v", got)
if !reflect.DeepEqual(got, in) {
t.Fatalf("round trip lost data: want %#v, got %#v", in, got)
}
}
go test ./filter/generic/generalizer \
-run TestMapGeneralizerMTagRoundTrip \
-count=1 -v
### ✅ 预期行为
Payload{UserID: "42", Name: "alice"}
### ❌ 实际行为
generalized: map[string]interface {}{
"name": "alice",
"user_id": "42",
}
realized: Payload{
UserID: "",
Name: "alice",
}
round trip lost data
### 💡 可能的解决方案
_No response_
✅ 验证清单
🚀 Go 版本
1.26.1
📦 Dubbo-go 版本
v 3.3.0
🖥️ 服务端配置
No response
💻 客户端配置
No response
🌐 协议配置
No response
📋 注册中心配置
No response
💾 操作系统
🍎 macOS
📝 Bug 描述
MapGeneralizer.Generalizeuses themstruct tag as the generated map key,but
MapGeneralizer.Realizedoes not use the same tag when decoding the map.Realizecallsmapstructure.Decodewith its default configuration.mapstructure defaults to the
mapstructuretag and only performscase-insensitive field-name matching.
As a result, an
mtag that genuinely renames a field, such asUserID -> user_id, cannot be mapped back. The key is silently ignored,the target field remains its zero value, and no error is returned.
This affects the default
generic=truemap generalization mode, includinggeneric request arguments, generic responses, and
GenericService.InvokeWithType.🔄 重现步骤
Create
filter/generic/generalizer/m_tag_repro_test.go: