Merge pull request #229 from wongoo/fix-223
Fix decoding error for map in map
diff --git a/map.go b/map.go
index feec8fa..dc7a21b 100644
--- a/map.go
+++ b/map.go
@@ -268,9 +268,13 @@
if !ok {
return nil, perrors.Errorf("the type of map key must be string, but get %v", k)
}
- fieldValue = instValue.FieldByName(fieldName)
- if fieldValue.IsValid() {
- fieldValue.Set(EnsureRawValue(v))
+ if instValue.Kind() == reflect.Map {
+ instValue.SetMapIndex(reflect.ValueOf(k), EnsureRawValue(v))
+ } else {
+ fieldValue = instValue.FieldByName(fieldName)
+ if fieldValue.IsValid() {
+ fieldValue.Set(EnsureRawValue(v))
+ }
}
}
_, err = d.readByte()
@@ -280,6 +284,9 @@
return inst, nil
} else {
m = make(map[interface{}]interface{})
+ classIndex := RegisterPOJOMapping(t, m)
+ d.appendClsDef(pojoRegistry.classInfoList[classIndex])
+
d.appendRefs(m)
for d.peekByte() != BC_END {
k, err = d.Decode()
diff --git a/map_test.go b/map_test.go
index e349f7b..b63827d 100644
--- a/map_test.go
+++ b/map_test.go
@@ -96,3 +96,14 @@
testJavaDecode(t, "argUntypedMap_1", map[interface{}]interface{}{"a": int32(0)})
testJavaDecode(t, "argUntypedMap_2", map[interface{}]interface{}{int32(0): "a", int32(1): "b"})
}
+
+func TestCustomMap(t *testing.T) {
+ testDecodeFramework(t, "customReplyMap", map[interface{}]interface{}{"a": int32(1), "b": int32(2)})
+
+ mapInMap := map[interface{}]interface{}{
+ "obj1": map[interface{}]interface{}{"a": int32(1)},
+ "obj2": map[interface{}]interface{}{"b": int32(2)},
+ }
+ testDecodeFramework(t, "customReplyMapInMap", mapInMap)
+ testDecodeFramework(t, "customReplyMapInMapJsonObject", mapInMap)
+}
diff --git a/pojo.go b/pojo.go
index bf11633..8ed2e42 100644
--- a/pojo.go
+++ b/pojo.go
@@ -115,17 +115,22 @@
// RegisterPOJO Register a POJO instance. The return value is -1 if @o has been registered.
func RegisterPOJO(o POJO) int {
+ return RegisterPOJOMapping(o.JavaClassName(), o)
+}
+
+// RegisterPOJOMapping Register a POJO instance. The return value is -1 if @o has been registered.
+func RegisterPOJOMapping(javaClassName string, o interface{}) int {
// # definition for an object (compact map)
// class-def ::= 'C' string int string*
pojoRegistry.Lock()
defer pojoRegistry.Unlock()
- if goName, ok := pojoRegistry.j2g[o.JavaClassName()]; ok {
+ if goName, ok := pojoRegistry.j2g[javaClassName]; ok {
return pojoRegistry.registry[goName].index
}
// JavaClassName shouldn't equal to goName
- if _, ok := pojoRegistry.registry[o.JavaClassName()]; ok {
+ if _, ok := pojoRegistry.registry[javaClassName]; ok {
return -1
}
@@ -140,7 +145,7 @@
structInfo.typ = obtainValueType(o)
structInfo.goName = structInfo.typ.String()
- structInfo.javaName = o.JavaClassName()
+ structInfo.javaName = javaClassName
structInfo.inst = o
pojoRegistry.j2g[structInfo.javaName] = structInfo.goName
registerTypeName(structInfo.goName, structInfo.javaName)
@@ -149,37 +154,37 @@
nextStruct := []reflect.Type{structInfo.typ}
for len(nextStruct) > 0 {
current := nextStruct[0]
+ if current.Kind() == reflect.Struct {
+ for i := 0; i < current.NumField(); i++ {
+ // skip unexported anonymous filed
+ if current.Field(i).PkgPath != "" {
+ continue
+ }
- for i := 0; i < current.NumField(); i++ {
+ structField := current.Field(i)
- // skip unexported anonymous filed
- if current.Field(i).PkgPath != "" {
- continue
+ // skip ignored field
+ tagVal, hasTag := structField.Tag.Lookup(tagIdentifier)
+ if tagVal == `-` {
+ continue
+ }
+
+ // flat anonymous field
+ if structField.Anonymous && structField.Type.Kind() == reflect.Struct {
+ nextStruct = append(nextStruct, structField.Type)
+ continue
+ }
+
+ var fieldName string
+ if hasTag {
+ fieldName = tagVal
+ } else {
+ fieldName = lowerCamelCase(structField.Name)
+ }
+
+ fieldList = append(fieldList, fieldName)
+ bBody = encString(bBody, fieldName)
}
-
- structField := current.Field(i)
-
- // skip ignored field
- tagVal, hasTag := structField.Tag.Lookup(tagIdentifier)
- if tagVal == `-` {
- continue
- }
-
- // flat anonymous field
- if structField.Anonymous && structField.Type.Kind() == reflect.Struct {
- nextStruct = append(nextStruct, structField.Type)
- continue
- }
-
- var fieldName string
- if hasTag {
- fieldName = tagVal
- } else {
- fieldName = lowerCamelCase(structField.Name)
- }
-
- fieldList = append(fieldList, fieldName)
- bBody = encString(bBody, fieldName)
}
nextStruct = nextStruct[1:]
@@ -235,7 +240,7 @@
return -1
}
-func obtainValueType(o POJO) reflect.Type {
+func obtainValueType(o interface{}) reflect.Type {
v := reflect.ValueOf(o)
switch v.Kind() {
case reflect.Struct:
@@ -385,6 +390,10 @@
return nil
}
+ if s.typ.Kind() == reflect.Map {
+ return reflect.MakeMap(s.typ).Interface()
+ }
+
return reflect.New(s.typ).Interface()
}
diff --git a/test_hessian/pom.xml b/test_hessian/pom.xml
index acd9188..a4db3f1 100644
--- a/test_hessian/pom.xml
+++ b/test_hessian/pom.xml
@@ -48,6 +48,11 @@
<version>2.6.5</version>
</dependency>
<dependency>
+ <groupId>com.alibaba</groupId>
+ <artifactId>fastjson</artifactId>
+ <version>1.2.70</version>
+ </dependency>
+ <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
diff --git a/test_hessian/src/main/java/test/TestCustomReply.java b/test_hessian/src/main/java/test/TestCustomReply.java
index 12fc411..62e3ea6 100644
--- a/test_hessian/src/main/java/test/TestCustomReply.java
+++ b/test_hessian/src/main/java/test/TestCustomReply.java
@@ -18,8 +18,12 @@
package test;
import com.alibaba.com.caucho.hessian.io.Hessian2Output;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
import com.caucho.hessian.test.A0;
import com.caucho.hessian.test.A1;
+import test.model.DateDemo;
+
import java.io.OutputStream;
import java.io.Serializable;
import java.math.BigDecimal;
@@ -27,17 +31,16 @@
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
-import test.model.DateDemo;
-
public class TestCustomReply {
private Hessian2Output output;
private HashMap<Class<?>, String> typeMap;
- TestCustomReply(OutputStream os) {
+ public TestCustomReply(OutputStream os) {
output = new Hessian2Output(os);
typeMap = new HashMap<>();
@@ -355,32 +358,32 @@
}
public void customReplyTypedFixedList_BigInteger() throws Exception {
- BigInteger[] integers = new BigInteger[] {
- new BigInteger("1234"),
- new BigInteger("12347890"),
- new BigInteger("123478901234"),
- new BigInteger("1234789012345678"),
- new BigInteger("123478901234567890"),
- new BigInteger("1234789012345678901234"),
- new BigInteger("12347890123456789012345678"),
- new BigInteger("123478901234567890123456781234"),
- new BigInteger("1234789012345678901234567812345678"),
- new BigInteger("12347890123456789012345678123456781234"),
- new BigInteger("-12347890123456789012345678123456781234"),
- new BigInteger("0"),
+ BigInteger[] integers = new BigInteger[]{
+ new BigInteger("1234"),
+ new BigInteger("12347890"),
+ new BigInteger("123478901234"),
+ new BigInteger("1234789012345678"),
+ new BigInteger("123478901234567890"),
+ new BigInteger("1234789012345678901234"),
+ new BigInteger("12347890123456789012345678"),
+ new BigInteger("123478901234567890123456781234"),
+ new BigInteger("1234789012345678901234567812345678"),
+ new BigInteger("12347890123456789012345678123456781234"),
+ new BigInteger("-12347890123456789012345678123456781234"),
+ new BigInteger("0"),
};
output.writeObject(integers);
output.flush();
}
public void customReplyTypedFixedList_CustomObject() throws Exception {
- Object[] objects = new Object[] {
- new BigInteger("1234"),
- new BigInteger("-12347890"),
- new BigInteger("0"),
- new BigDecimal("123.4"),
- new BigDecimal("-123.45"),
- new BigDecimal("0"),
+ Object[] objects = new Object[]{
+ new BigInteger("1234"),
+ new BigInteger("-12347890"),
+ new BigInteger("0"),
+ new BigDecimal("123.4"),
+ new BigDecimal("-123.45"),
+ new BigDecimal("0"),
};
output.writeObject(objects);
output.flush();
@@ -473,6 +476,37 @@
output.writeObject(set);
output.flush();
}
+
+ public void customReplyMap() throws Exception {
+ Map<String, Object> map = new HashMap<String, Object>(4);
+ map.put("a", 1);
+ map.put("b", 2);
+ output.writeObject(map);
+ output.flush();
+ }
+
+ public Map<String, Object> mapInMap() throws Exception {
+ Map<String, Object> map1 = new HashMap<String, Object>();
+ map1.put("a", 1);
+ Map<String, Object> map2 = new HashMap<String, Object>();
+ map2.put("b", 2);
+
+ Map<String, Object> map = new HashMap<String, Object>();
+ map.put("obj1", map1);
+ map.put("obj2", map2);
+ return map;
+ }
+
+ public void customReplyMapInMap() throws Exception {
+ output.writeObject(mapInMap());
+ output.flush();
+ }
+
+ public void customReplyMapInMapJsonObject() throws Exception {
+ JSONObject json = JSON.parseObject(JSON.toJSONString(mapInMap()));
+ output.writeObject(json);
+ output.flush();
+ }
}
interface Leg {