This is an automated email from the ASF dual-hosted git repository.
alexstocks pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/dubbo-go.git
The following commit(s) were added to refs/heads/develop by this push:
new 86208c743 feat(generic): add bean generalizer to support generic=bean
serialization (#3175)
86208c743 is described below
commit 86208c7439a3ad751aa6c654c29425f745010248
Author: CAICAII <[email protected]>
AuthorDate: Tue Jan 27 10:19:10 2026 +0800
feat(generic): add bean generalizer to support generic=bean serialization
(#3175)
* feat(generic): add bean generalizer for generic=bean serialization
Add JavaBeanDescriptor support to handle Java Dubbo services configured
with generic=bean, enabling dubbo-go to serialize/deserialize objects
using the JavaBeanDescriptor format.
Signed-off-by: dubbo-go <[email protected]>
* feat(generic): integrate bean generalizer into generic filter
- Add GenericSerializationBean constant in common/constant/key.go
- Update isGeneric() to recognize bean as a valid generic type
- Update getGeneralizer() to return BeanGeneralizer for generic=bean
- Add test cases for bean serialization support
Signed-off-by: dubbo-go <[email protected]>
* style: fix testifylint errors in bean_test.go
- Replace assert.Nil(t, err) with assert.NoError(t, err)
- Replace assert.Equal(t, n, len(...)) with assert.Len(t, ..., n)
Signed-off-by: dubbo-go <[email protected]>
* style: use require.NoError for error assertions in bean_test.go
Replace assert.NoError with require.NoError where subsequent code
depends on the error being nil, per testifylint rules.
Signed-off-by: dubbo-go <[email protected]>
* style: replace all assert.NoError with require.NoError in bean_test.go
Per testifylint rules, use require.NoError for error assertions where
subsequent code depends on the error being nil (e.g., type assertions).
Signed-off-by: dubbo-go <[email protected]>
* fix(generic): address Copilot review comments for bean generalizer
- Handle typed nil pointer (e.g., (*T)(nil)) in toDescriptor
- Fix Java Hessian interop: normalize int32/int64 keys to int for arrays
- Add GetType fallback to java.lang.Object for nil/unrecognized types
- Reuse toUnexport function for field name conversion
- Extract toInt helper to reduce code duplication
- Add tests for typed nil pointer and int32 key scenarios
Signed-off-by: dubbo-go <[email protected]>
* fix(generic): handle circular reference in bean generalizer and add type
constants documentation
- Add circular reference detection in toDescriptor using visited map
- Add documentation for type constants explaining Java interoperability
- Remove redundant comment in util_test.go
- Add test cases for self-referencing and mutual circular references
Signed-off-by: CAICAIIs <[email protected]>
---------
Signed-off-by: dubbo-go <[email protected]>
Signed-off-by: CAICAIIs <[email protected]>
---
common/constant/key.go | 1 +
filter/generic/generalizer/bean.go | 252 ++++++++++++++++++++++++++
filter/generic/generalizer/bean_test.go | 312 ++++++++++++++++++++++++++++++++
filter/generic/util.go | 5 +-
filter/generic/util_test.go | 9 +-
5 files changed, 575 insertions(+), 4 deletions(-)
diff --git a/common/constant/key.go b/common/constant/key.go
index 4f40d9989..5cc333f20 100644
--- a/common/constant/key.go
+++ b/common/constant/key.go
@@ -417,6 +417,7 @@ const (
GenericSerializationGson = "gson"
GenericSerializationProtobuf = "protobuf"
GenericSerializationProtobufJson = "protobuf-json"
+ GenericSerializationBean = "bean"
GenericIncludeClassKey = "generic.include.class"
)
diff --git a/filter/generic/generalizer/bean.go
b/filter/generic/generalizer/bean.go
new file mode 100644
index 000000000..e8fd04207
--- /dev/null
+++ b/filter/generic/generalizer/bean.go
@@ -0,0 +1,252 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package generalizer
+
+import (
+ "reflect"
+ "sync"
+)
+
+import (
+ hessian "github.com/apache/dubbo-go-hessian2"
+)
+
+import (
+ "dubbo.apache.org/dubbo-go/v3/protocol/dubbo/hessian2"
+)
+
+// JavaBeanDescriptor type constants.
+// These constants are defined for Java interoperability with
org.apache.dubbo.common.beanutil.JavaBeanDescriptor.
+// Note: toDescriptor() (Go → Java) only produces TypePrimitive, TypeArray,
TypeMap, and TypeBean,
+// because Go doesn't have native enum or class concepts. However,
fromDescriptor() (Java → Go)
+// handles all types including TypeClass, TypeEnum, and TypeCollection for
full compatibility.
+const (
+ TypeClass = 1
+ TypeEnum = 2
+ TypeCollection = 3
+ TypeMap = 4
+ TypeArray = 5
+ TypePrimitive = 6
+ TypeBean = 7
+)
+
+// JavaBeanDescriptor corresponds to
org.apache.dubbo.common.beanutil.JavaBeanDescriptor
+type JavaBeanDescriptor struct {
+ ClassName string `json:"className"`
+ Type int `json:"type"`
+ Properties map[any]any `json:"properties"`
+}
+
+// JavaClassName implements hessian.POJO
+func (d *JavaBeanDescriptor) JavaClassName() string {
+ return "org.apache.dubbo.common.beanutil.JavaBeanDescriptor"
+}
+
+func init() {
+ hessian.RegisterPOJO(&JavaBeanDescriptor{})
+}
+
+var (
+ beanGeneralizer Generalizer
+ beanGeneralizerOnce sync.Once
+)
+
+func GetBeanGeneralizer() Generalizer {
+ beanGeneralizerOnce.Do(func() {
+ beanGeneralizer = &BeanGeneralizer{}
+ })
+ return beanGeneralizer
+}
+
+// BeanGeneralizer converts objects to/from JavaBeanDescriptor format
+type BeanGeneralizer struct{}
+
+func (g *BeanGeneralizer) Generalize(obj any) (any, error) {
+ if obj == nil {
+ return nil, nil
+ }
+ return g.toDescriptor(obj, make(map[uintptr]bool)), nil
+}
+
+func (g *BeanGeneralizer) Realize(obj any, typ reflect.Type) (any, error) {
+ if obj == nil {
+ return nil, nil
+ }
+ return GetMapGeneralizer().Realize(g.fromDescriptor(obj), typ)
+}
+
+func (g *BeanGeneralizer) GetType(obj any) (typ string, err error) {
+ typ, err = hessian2.GetJavaName(obj)
+ // no error or error is not NilError
+ if err == nil || err != hessian2.NilError {
+ return
+ }
+
+ // fallback to java.lang.Object for nil or unrecognized types
+ typ = "java.lang.Object"
+ err = nil
+ return
+}
+
+// toDescriptor converts Go object to JavaBeanDescriptor with circular
reference detection
+func (g *BeanGeneralizer) toDescriptor(obj any, visited map[uintptr]bool)
*JavaBeanDescriptor {
+ if obj == nil {
+ return nil
+ }
+
+ v := reflect.ValueOf(obj)
+ // Handle typed nil pointer (e.g., (*T)(nil) stored in an any)
+ if v.Kind() == reflect.Ptr && v.IsNil() {
+ return nil
+ }
+
+ // Check for circular reference
+ if v.Kind() == reflect.Ptr {
+ ptr := v.Pointer()
+ if visited[ptr] {
+ return nil // circular reference detected, return nil
to break the cycle
+ }
+ visited[ptr] = true
+ }
+
+ for v.Kind() == reflect.Ptr && !v.IsNil() {
+ v = v.Elem()
+ }
+ t := v.Type()
+
+ className := "java.lang.Object"
+ if pojo, ok := obj.(hessian.POJO); ok {
+ className = pojo.JavaClassName()
+ }
+
+ desc := &JavaBeanDescriptor{ClassName: className, Properties:
make(map[any]any)}
+
+ switch t.Kind() {
+ case reflect.Bool, reflect.Int, reflect.Int8, reflect.Int16,
reflect.Int32, reflect.Int64,
+ reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32,
reflect.Uint64,
+ reflect.Float32, reflect.Float64, reflect.String:
+ desc.Type = TypePrimitive
+ desc.Properties["value"] = v.Interface()
+
+ case reflect.Slice, reflect.Array:
+ desc.Type = TypeArray
+ for i := 0; i < v.Len(); i++ {
+ desc.Properties[i] =
g.toDescriptor(v.Index(i).Interface(), visited)
+ }
+
+ case reflect.Map:
+ desc.Type = TypeMap
+ iter := v.MapRange()
+ for iter.Next() {
+ desc.Properties[g.toDescriptor(iter.Key().Interface(),
visited)] = g.toDescriptor(iter.Value().Interface(), visited)
+ }
+
+ case reflect.Struct:
+ desc.Type = TypeBean
+ for i := 0; i < t.NumField(); i++ {
+ if fv := v.Field(i); fv.CanInterface() {
+ desc.Properties[toUnexport(t.Field(i).Name)] =
g.toDescriptor(fv.Interface(), visited)
+ }
+ }
+
+ default:
+ desc.Type = TypeBean
+ }
+
+ return desc
+}
+
+// fromDescriptor converts JavaBeanDescriptor to map for MapGeneralizer.Realize
+func (g *BeanGeneralizer) fromDescriptor(obj any) any {
+ desc, ok := obj.(*JavaBeanDescriptor)
+ if !ok {
+ if m, ok := obj.(map[any]any); ok {
+ desc = &JavaBeanDescriptor{Properties:
make(map[any]any)}
+ if v, ok := m["className"].(string); ok {
+ desc.ClassName = v
+ }
+ if v, ok := toInt(m["type"]); ok {
+ desc.Type = v
+ }
+ if v, ok := m["properties"].(map[any]any); ok {
+ desc.Properties = v
+ }
+ } else {
+ return obj
+ }
+ }
+
+ switch desc.Type {
+ case TypePrimitive:
+ return desc.Properties["value"]
+ case TypeEnum:
+ return desc.Properties["name"]
+ case TypeArray, TypeCollection:
+ // Normalize numeric keys (int, int32, int64) to indices when
rebuilding arrays/collections.
+ // Java Hessian decodes integer keys as int32, so we need to
handle type conversion.
+ maxIndex := -1
+ for k := range desc.Properties {
+ if idx, ok := toInt(k); ok && idx > maxIndex {
+ maxIndex = idx
+ }
+ }
+ if maxIndex < 0 {
+ return []any{}
+ }
+ result := make([]any, maxIndex+1)
+ for k, v := range desc.Properties {
+ if idx, ok := toInt(k); ok && idx >= 0 && idx <
len(result) {
+ result[idx] = g.fromDescriptor(v)
+ }
+ }
+ return result
+ case TypeMap:
+ result := make(map[any]any)
+ for k, v := range desc.Properties {
+ result[g.fromDescriptor(k)] = g.fromDescriptor(v)
+ }
+ return result
+ case TypeBean:
+ result := make(map[string]any)
+ if desc.ClassName != "" {
+ result["class"] = desc.ClassName
+ }
+ for k, v := range desc.Properties {
+ if ks, ok := k.(string); ok {
+ result[ks] = g.fromDescriptor(v)
+ }
+ }
+ return result
+ }
+ return obj
+}
+
+// toInt converts various integer types to int.
+// Returns the converted value and true if successful, otherwise 0 and false.
+func toInt(v any) (int, bool) {
+ switch n := v.(type) {
+ case int:
+ return n, true
+ case int32:
+ return int(n), true
+ case int64:
+ return int(n), true
+ default:
+ return 0, false
+ }
+}
diff --git a/filter/generic/generalizer/bean_test.go
b/filter/generic/generalizer/bean_test.go
new file mode 100644
index 000000000..3b6255f7f
--- /dev/null
+++ b/filter/generic/generalizer/bean_test.go
@@ -0,0 +1,312 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package generalizer
+
+import (
+ "reflect"
+ "testing"
+)
+
+import (
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+// TestUser is a test struct for bean serialization
+type TestUser struct {
+ Name string
+ Age int
+ Address *TestAddress
+}
+
+func (t *TestUser) JavaClassName() string {
+ return "com.test.User"
+}
+
+// TestAddress is a nested test struct
+type TestAddress struct {
+ City string
+ ZipCode string
+}
+
+func (t *TestAddress) JavaClassName() string {
+ return "com.test.Address"
+}
+
+func TestBeanGeneralizer_Generalize_Primitive(t *testing.T) {
+ g := GetBeanGeneralizer()
+
+ // Test string
+ result, err := g.Generalize("hello")
+ require.NoError(t, err)
+ desc := result.(*JavaBeanDescriptor)
+ assert.Equal(t, TypePrimitive, desc.Type)
+ assert.Equal(t, "hello", desc.Properties["value"])
+
+ // Test int
+ result, err = g.Generalize(42)
+ require.NoError(t, err)
+ desc = result.(*JavaBeanDescriptor)
+ assert.Equal(t, TypePrimitive, desc.Type)
+ assert.Equal(t, 42, desc.Properties["value"])
+}
+
+func TestBeanGeneralizer_Generalize_Nil(t *testing.T) {
+ g := GetBeanGeneralizer()
+ result, err := g.Generalize(nil)
+ require.NoError(t, err)
+ assert.Nil(t, result)
+}
+
+func TestBeanGeneralizer_Generalize_TypedNilPointer(t *testing.T) {
+ g := GetBeanGeneralizer()
+
+ // Test typed nil pointer (e.g., (*TestAddress)(nil) stored in an any)
+ var addr *TestAddress = nil
+ result, err := g.Generalize(addr)
+ require.NoError(t, err)
+ assert.Nil(t, result)
+
+ // Test typed nil pointer in struct field
+ user := &TestUser{
+ Name: "John",
+ Age: 30,
+ Address: nil, // typed nil pointer field
+ }
+ result, err = g.Generalize(user)
+ require.NoError(t, err)
+ desc := result.(*JavaBeanDescriptor)
+ assert.Equal(t, TypeBean, desc.Type)
+ // The nil Address field should be nil in properties
+ assert.Nil(t, desc.Properties["address"])
+}
+
+func TestBeanGeneralizer_Generalize_Slice(t *testing.T) {
+ g := GetBeanGeneralizer()
+
+ result, err := g.Generalize([]string{"a", "b", "c"})
+ require.NoError(t, err)
+ desc := result.(*JavaBeanDescriptor)
+ assert.Equal(t, TypeArray, desc.Type)
+ assert.Len(t, desc.Properties, 3)
+}
+
+func TestBeanGeneralizer_Generalize_Map(t *testing.T) {
+ g := GetBeanGeneralizer()
+
+ result, err := g.Generalize(map[string]int{"one": 1, "two": 2})
+ require.NoError(t, err)
+ desc := result.(*JavaBeanDescriptor)
+ assert.Equal(t, TypeMap, desc.Type)
+ assert.Len(t, desc.Properties, 2)
+}
+
+func TestBeanGeneralizer_Generalize_Struct(t *testing.T) {
+ g := GetBeanGeneralizer()
+
+ user := &TestUser{
+ Name: "John",
+ Age: 30,
+ Address: &TestAddress{
+ City: "Beijing",
+ ZipCode: "100000",
+ },
+ }
+
+ result, err := g.Generalize(user)
+ require.NoError(t, err)
+ desc := result.(*JavaBeanDescriptor)
+ assert.Equal(t, TypeBean, desc.Type)
+ assert.Equal(t, "com.test.User", desc.ClassName)
+}
+
+func TestBeanGeneralizer_Realize_Primitive(t *testing.T) {
+ g := GetBeanGeneralizer()
+
+ desc := &JavaBeanDescriptor{
+ Type: TypePrimitive,
+ Properties: map[any]any{"value": "hello"},
+ }
+
+ result, err := g.Realize(desc, reflect.TypeOf(""))
+ require.NoError(t, err)
+ assert.Equal(t, "hello", result)
+}
+
+func TestBeanGeneralizer_Realize_Nil(t *testing.T) {
+ g := GetBeanGeneralizer()
+ result, err := g.Realize(nil, reflect.TypeOf(""))
+ require.NoError(t, err)
+ assert.Nil(t, result)
+}
+
+func TestBeanGeneralizer_RoundTrip_Struct(t *testing.T) {
+ g := GetBeanGeneralizer()
+
+ original := &TestUser{
+ Name: "Alice",
+ Age: 25,
+ Address: &TestAddress{
+ City: "Shanghai",
+ ZipCode: "200000",
+ },
+ }
+
+ generalized, err := g.Generalize(original)
+ require.NoError(t, err)
+
+ realized, err := g.Realize(generalized, reflect.TypeOf(&TestUser{}))
+ require.NoError(t, err)
+
+ user := realized.(*TestUser)
+ assert.Equal(t, original.Name, user.Name)
+ assert.Equal(t, original.Age, user.Age)
+ assert.NotNil(t, user.Address)
+ assert.Equal(t, original.Address.City, user.Address.City)
+}
+
+func TestBeanGeneralizer_RoundTrip_Slice(t *testing.T) {
+ g := GetBeanGeneralizer()
+
+ original := []int{1, 2, 3, 4, 5}
+
+ generalized, err := g.Generalize(original)
+ require.NoError(t, err)
+
+ realized, err := g.Realize(generalized, reflect.TypeOf([]int{}))
+ require.NoError(t, err)
+
+ slice := realized.([]int)
+ assert.Len(t, slice, len(original))
+}
+
+func TestBeanGeneralizer_RoundTrip_Map(t *testing.T) {
+ g := GetBeanGeneralizer()
+
+ original := map[string]string{"key1": "value1", "key2": "value2"}
+
+ generalized, err := g.Generalize(original)
+ require.NoError(t, err)
+
+ realized, err := g.Realize(generalized,
reflect.TypeOf(map[string]string{}))
+ require.NoError(t, err)
+
+ m := realized.(map[string]string)
+ assert.Len(t, m, len(original))
+}
+
+func TestJavaBeanDescriptor_JavaClassName(t *testing.T) {
+ desc := &JavaBeanDescriptor{}
+ assert.Equal(t, "org.apache.dubbo.common.beanutil.JavaBeanDescriptor",
desc.JavaClassName())
+}
+
+func TestGetBeanGeneralizer_Singleton(t *testing.T) {
+ g1 := GetBeanGeneralizer()
+ g2 := GetBeanGeneralizer()
+ assert.Same(t, g1, g2)
+}
+
+func TestBeanGeneralizer_GetType(t *testing.T) {
+ g := GetBeanGeneralizer()
+ typ, err := g.GetType(&TestUser{})
+ require.NoError(t, err)
+ assert.Equal(t, "com.test.User", typ)
+}
+
+func TestBeanGeneralizer_GetType_Nil(t *testing.T) {
+ g := GetBeanGeneralizer()
+ typ, err := g.GetType(nil)
+ require.NoError(t, err)
+ assert.Equal(t, "java.lang.Object", typ)
+}
+
+func TestBeanGeneralizer_Realize_ArrayWithInt32Keys(t *testing.T) {
+ g := GetBeanGeneralizer()
+
+ // Simulate JavaBeanDescriptor from Java Hessian with int32 keys
+ // Java Hessian decodes integer keys as int32, not int
+ desc := &JavaBeanDescriptor{
+ Type: TypeArray,
+ ClassName: "[Ljava.lang.String;",
+ Properties: map[any]any{
+ int32(0): &JavaBeanDescriptor{Type: TypePrimitive,
Properties: map[any]any{"value": "a"}},
+ int32(1): &JavaBeanDescriptor{Type: TypePrimitive,
Properties: map[any]any{"value": "b"}},
+ int32(2): &JavaBeanDescriptor{Type: TypePrimitive,
Properties: map[any]any{"value": "c"}},
+ },
+ }
+
+ realized, err := g.Realize(desc, reflect.TypeOf([]string{}))
+ require.NoError(t, err)
+
+ slice := realized.([]string)
+ assert.Len(t, slice, 3)
+ assert.Equal(t, "a", slice[0])
+ assert.Equal(t, "b", slice[1])
+ assert.Equal(t, "c", slice[2])
+}
+
+// CircularNode is a test struct for circular reference testing
+type CircularNode struct {
+ Name string
+ Next *CircularNode
+}
+
+func TestBeanGeneralizer_Generalize_CircularReference(t *testing.T) {
+ g := GetBeanGeneralizer()
+
+ // Create a circular reference: node -> node (self-referencing)
+ node := &CircularNode{Name: "node1"}
+ node.Next = node
+
+ // Should not panic or infinite loop
+ result, err := g.Generalize(node)
+ require.NoError(t, err)
+ assert.NotNil(t, result)
+
+ desc := result.(*JavaBeanDescriptor)
+ assert.Equal(t, TypeBean, desc.Type)
+ assert.Equal(t, "node1",
desc.Properties["name"].(*JavaBeanDescriptor).Properties["value"])
+ // The circular reference should be nil to break the cycle
+ assert.Nil(t, desc.Properties["next"])
+}
+
+func TestBeanGeneralizer_Generalize_MutualCircularReference(t *testing.T) {
+ g := GetBeanGeneralizer()
+
+ // Create mutual circular reference: node1 -> node2 -> node1
+ node1 := &CircularNode{Name: "node1"}
+ node2 := &CircularNode{Name: "node2"}
+ node1.Next = node2
+ node2.Next = node1
+
+ // Should not panic or infinite loop
+ result, err := g.Generalize(node1)
+ require.NoError(t, err)
+ assert.NotNil(t, result)
+
+ desc := result.(*JavaBeanDescriptor)
+ assert.Equal(t, TypeBean, desc.Type)
+ assert.Equal(t, "node1",
desc.Properties["name"].(*JavaBeanDescriptor).Properties["value"])
+
+ // node1.Next should be node2
+ node2Desc := desc.Properties["next"].(*JavaBeanDescriptor)
+ assert.Equal(t, "node2",
node2Desc.Properties["name"].(*JavaBeanDescriptor).Properties["value"])
+
+ // node2.Next should be nil (circular reference back to node1)
+ assert.Nil(t, node2Desc.Properties["next"])
+}
diff --git a/filter/generic/util.go b/filter/generic/util.go
index 17c1766c9..406e610db 100644
--- a/filter/generic/util.go
+++ b/filter/generic/util.go
@@ -54,7 +54,8 @@ func isMakingAGenericCall(invoker base.Invoker, invocation
base.Invocation) bool
func isGeneric(generic string) bool {
return strings.EqualFold(generic, constant.GenericSerializationDefault)
||
strings.EqualFold(generic, constant.GenericSerializationGson) ||
- strings.EqualFold(generic,
constant.GenericSerializationProtobufJson)
+ strings.EqualFold(generic,
constant.GenericSerializationProtobufJson) ||
+ strings.EqualFold(generic, constant.GenericSerializationBean)
}
func getGeneralizer(generic string) (g generalizer.Generalizer) {
@@ -65,6 +66,8 @@ func getGeneralizer(generic string) (g
generalizer.Generalizer) {
g = generalizer.GetGsonGeneralizer()
case strings.EqualFold(generic,
constant.GenericSerializationProtobufJson):
g = generalizer.GetProtobufJsonGeneralizer()
+ case strings.EqualFold(generic, constant.GenericSerializationBean):
+ g = generalizer.GetBeanGeneralizer()
default:
logger.Debugf("\"%s\" is not supported, use the default
generalizer(MapGeneralizer)", generic)
g = generalizer.GetMapGeneralizer()
diff --git a/filter/generic/util_test.go b/filter/generic/util_test.go
index 42d8603a3..646c2d5a6 100644
--- a/filter/generic/util_test.go
+++ b/filter/generic/util_test.go
@@ -81,7 +81,7 @@ func TestIsGeneric(t *testing.T) {
assert.True(t, isGeneric("Protobuf-Json"))
assert.False(t, isGeneric("false"))
assert.False(t, isGeneric(""))
- assert.False(t, isGeneric("bean"))
+ assert.True(t, isGeneric("bean"))
}
func TestGetGeneralizer(t *testing.T) {
@@ -98,6 +98,9 @@ func TestGetGeneralizer(t *testing.T) {
g4 := getGeneralizer("Protobuf-Json")
assert.IsType(t, generalizer.GetProtobufJsonGeneralizer(), g4)
- g5 := getGeneralizer("unsupported_type")
- assert.IsType(t, generalizer.GetMapGeneralizer(), g5)
+ g5 := getGeneralizer(constant.GenericSerializationBean)
+ assert.IsType(t, generalizer.GetBeanGeneralizer(), g5)
+
+ g6 := getGeneralizer("unsupported_type")
+ assert.IsType(t, generalizer.GetMapGeneralizer(), g6)
}