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)
 }

Reply via email to