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