This is an automated email from the ASF dual-hosted git repository.

alexstocks pushed a commit to branch 3.0
in repository https://gitbox.apache.org/repos/asf/dubbo-go.git


The following commit(s) were added to refs/heads/3.0 by this push:
     new 103cf14  Ftr: add json generalizer (#1343)
103cf14 is described below

commit 103cf14dc0ff16f08b66ca304fd2129b4bd36f24
Author: EnableAsync <[email protected]>
AuthorDate: Wed Jul 28 10:29:52 2021 +0800

    Ftr: add json generalizer (#1343)
    
    * Ftr: add json generalizer
    
    Fix: go fmt
    
    * Fix: hessian pojo
    
    * fix: restart ci
    
    * Fix: imports format
---
 common/constant/key.go                  |  1 +
 filter/generic/generalizer/gson.go      | 99 +++++++++++++++++++++++++++++++++
 filter/generic/generalizer/gson_test.go | 97 ++++++++++++++++++++++++++++++++
 filter/generic/util.go                  |  3 +
 4 files changed, 200 insertions(+)

diff --git a/common/constant/key.go b/common/constant/key.go
index 54a3c26..ae27581 100644
--- a/common/constant/key.go
+++ b/common/constant/key.go
@@ -314,4 +314,5 @@ const (
        GenericSerializationDefault = "true"
        // disable "protobuf-json" temporarily
        //GenericSerializationProtobuf = "protobuf-json"
+       GenericSerializationGson = "gson"
 )
diff --git a/filter/generic/generalizer/gson.go 
b/filter/generic/generalizer/gson.go
new file mode 100644
index 0000000..ffa2114
--- /dev/null
+++ b/filter/generic/generalizer/gson.go
@@ -0,0 +1,99 @@
+/*
+ * 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 (
+       "encoding/json"
+       "reflect"
+       "sync"
+)
+
+import (
+       hessian "github.com/apache/dubbo-go-hessian2"
+       perrors "github.com/pkg/errors"
+)
+
+import (
+       "dubbo.apache.org/dubbo-go/v3/common/logger"
+       "dubbo.apache.org/dubbo-go/v3/protocol/dubbo/hessian2"
+)
+
+var (
+       jsonGeneralizer     Generalizer
+       jsonGeneralizerOnce sync.Once
+)
+
+func GetGsonGeneralizer() Generalizer {
+       jsonGeneralizerOnce.Do(func() {
+               jsonGeneralizer = &GsonGeneralizer{}
+       })
+       return jsonGeneralizer
+}
+
+type GsonGeneralizer struct{}
+
+func (GsonGeneralizer) Generalize(obj interface{}) (interface{}, error) {
+       newObj, ok := obj.(hessian.POJO)
+       if !ok {
+               return nil, perrors.Errorf("unexpected type of obj(=%T), wanted 
is hessian pojo", obj)
+       }
+
+       jsonbytes, err := json.Marshal(newObj)
+       if err != nil {
+               return nil, err
+       }
+
+       return string(jsonbytes), nil
+}
+
+func (GsonGeneralizer) Realize(obj interface{}, typ reflect.Type) 
(interface{}, error) {
+       jsonbytes, ok := obj.(string)
+       if !ok {
+               return nil, perrors.Errorf("unexpected type of obj(=%T), wanted 
is string", obj)
+       }
+
+       // create the target object
+       ret, ok := reflect.New(typ).Interface().(hessian.POJO)
+       if !ok {
+               return nil, perrors.Errorf("the type of obj(=%s) should be 
hessian pojo", typ)
+       }
+
+       err := json.Unmarshal([]byte(jsonbytes), ret)
+       if err != nil {
+               return nil, err
+       }
+
+       return ret, nil
+}
+
+func (GsonGeneralizer) GetType(obj interface{}) (typ string, err error) {
+       typ, err = hessian2.GetJavaName(obj)
+       // no error or error is not NilError
+       if err == nil || err != hessian2.NilError {
+               return
+       }
+
+       typ = "java.lang.Object"
+       if err == hessian2.NilError {
+               logger.Debugf("the type of nil object couldn't be inferred, use 
the default value(\"%s\")", typ)
+               return
+       }
+
+       logger.Debugf("the type of object(=%T) couldn't be recognized as a 
POJO, use the default value(\"%s\")", obj, typ)
+       return
+}
diff --git a/filter/generic/generalizer/gson_test.go 
b/filter/generic/generalizer/gson_test.go
new file mode 100644
index 0000000..96006f0
--- /dev/null
+++ b/filter/generic/generalizer/gson_test.go
@@ -0,0 +1,97 @@
+/*
+ * 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"
+)
+
+var mockGsonGeneralizer = GetGsonGeneralizer()
+
+type mockGsonParent struct {
+       Gender, Email, Name string
+       Age                 int
+       Child               *mockGsonChild
+}
+
+func (p mockGsonParent) JavaClassName() string {
+       return "org.apache.dubbo.mockGsonParent"
+}
+
+type mockGsonChild struct {
+       Gender, Email, Name string
+       Age                 int
+}
+
+func (p mockGsonChild) JavaClassName() string {
+       return "org.apache.dubbo.mockGsonChild"
+}
+
+func TestGsonGeneralizer(t *testing.T) {
+       c := &mockGsonChild{
+               Age:    20,
+               Gender: "male",
+               Email:  "[email protected]",
+               Name:   "childName",
+       }
+       p := mockGsonParent{
+               Age:    30,
+               Gender: "male",
+               Email:  "[email protected]",
+               Name:   "enableasync",
+               Child:  c,
+       }
+
+       m, err := mockGsonGeneralizer.Generalize(p)
+       assert.Nil(t, err)
+       assert.Equal(t, 
"{\"Gender\":\"male\",\"Email\":\"[email protected]\",\"Name\":\"enableasync\",\"Age\":30,\"Child\":{\"Gender\":\"male\",\"Email\":\"[email protected]\",\"Name\":\"childName\",\"Age\":20}}",
 m)
+
+       r, err := mockGsonGeneralizer.Realize(m, reflect.TypeOf(p))
+       assert.Nil(t, err)
+       rMockParent, ok := r.(*mockGsonParent)
+       assert.True(t, ok)
+       // parent
+       assert.Equal(t, "enableasync", rMockParent.Name)
+       assert.Equal(t, 30, rMockParent.Age)
+       // child
+       assert.Equal(t, "childName", rMockParent.Child.Name)
+       assert.Equal(t, 20, rMockParent.Child.Age)
+}
+
+func TestGsonPointer(t *testing.T) {
+       c := &mockGsonChild{
+               Age:    20,
+               Gender: "male",
+               Email:  "[email protected]",
+               Name:   "childName",
+       }
+
+       m, err := mockMapGeneralizer.Generalize(c)
+       assert.Nil(t, err)
+       newC, err := mockMapGeneralizer.Realize(m, reflect.TypeOf(c))
+       assert.Nil(t, err)
+       rMockChild, ok := newC.(*mockGsonChild)
+       assert.True(t, ok)
+       assert.Equal(t, "childName", rMockChild.Name)
+       assert.Equal(t, 20, rMockChild.Age)
+}
diff --git a/filter/generic/util.go b/filter/generic/util.go
index 61ad4a4..a7fe467 100644
--- a/filter/generic/util.go
+++ b/filter/generic/util.go
@@ -69,6 +69,9 @@ func getGeneralizer(generic string) (g 
generalizer.Generalizer) {
        switch strings.ToLower(generic) {
        case constant.GenericSerializationDefault:
                g = generalizer.GetMapGeneralizer()
+       case constant.GenericSerializationGson:
+               g = generalizer.GetGsonGeneralizer()
+
        default:
                logger.Debugf("\"%s\" is not supported, use the default 
generalizer(MapGeneralizer)", generic)
                g = generalizer.GetMapGeneralizer()

Reply via email to