From fba2f73681d28cbae0d04e68ec644d991170da59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B8=A9=E5=B0=91?= Date: Tue, 22 May 2012 09:41:49 +0800 Subject: [PATCH] support JSONType.orders --- pom.xml | 9 +- .../serializer/ASMSerializerFactory.java | 6 +- .../serializer/JavaBeanSerializer.java | 31 ++-- .../fastjson/serializer/SerializeWriter.java | 4 +- .../serializer/SerializerFeature.java | 7 +- .../com/alibaba/fastjson/util/TypeUtils.java | 49 ++++++- .../com/alibaba/json/bvt/JSONTypeTest.java | 132 ++++++++++++++++++ .../com/alibaba/json/bvt/TestForEmoji.java | 4 + .../json/test/benchmark/BenchmarkTest.java | 8 +- .../json/test/codec/Jackson2Codec.java | 63 +++++++++ 10 files changed, 283 insertions(+), 30 deletions(-) create mode 100644 src/test/java/com/alibaba/json/bvt/JSONTypeTest.java create mode 100644 src/test/java/com/alibaba/json/test/codec/Jackson2Codec.java diff --git a/pom.xml b/pom.xml index 6097038c1..4fa22e7c3 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 com.alibaba fastjson - 1.1.19 + 1.1.20-SNAPSHOT jar fastjson @@ -186,6 +186,13 @@ + + com.fasterxml.jackson.core + jackson-databind + 2.0.1 + test + + org.codehaus.jackson jackson-core-lgpl diff --git a/src/main/java/com/alibaba/fastjson/serializer/ASMSerializerFactory.java b/src/main/java/com/alibaba/fastjson/serializer/ASMSerializerFactory.java index 5180df3ea..646dbe1f0 100644 --- a/src/main/java/com/alibaba/fastjson/serializer/ASMSerializerFactory.java +++ b/src/main/java/com/alibaba/fastjson/serializer/ASMSerializerFactory.java @@ -9,7 +9,6 @@ import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.math.BigDecimal; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -114,7 +113,7 @@ public class ASMSerializerFactory implements Opcodes { throw new JSONException("unsupportd class " + clazz.getName()); } - List getters = TypeUtils.computeGetters(clazz, aliasMap); + List getters = TypeUtils.computeGetters(clazz, aliasMap, false); String className = getGenClassName(clazz); @@ -212,8 +211,7 @@ public class ASMSerializerFactory implements Opcodes { } { - List sortedGetters = TypeUtils.computeGetters(clazz, aliasMap); - Collections.sort(sortedGetters); + List sortedGetters = TypeUtils.computeGetters(clazz, aliasMap, true); // sortField support Context context = new Context(className); diff --git a/src/main/java/com/alibaba/fastjson/serializer/JavaBeanSerializer.java b/src/main/java/com/alibaba/fastjson/serializer/JavaBeanSerializer.java index 38c2ab144..a4a0eb3c3 100644 --- a/src/main/java/com/alibaba/fastjson/serializer/JavaBeanSerializer.java +++ b/src/main/java/com/alibaba/fastjson/serializer/JavaBeanSerializer.java @@ -20,7 +20,6 @@ import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.lang.reflect.Type; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -60,18 +59,26 @@ public class JavaBeanSerializer implements ObjectSerializer { } public JavaBeanSerializer(Class clazz, Map aliasMap){ - List getterList = new ArrayList(); - - List fieldInfoList = TypeUtils.computeGetters(clazz, aliasMap); - - for (FieldInfo fieldInfo : fieldInfoList) { - getterList.add(createFieldSerializer(fieldInfo)); + { + List getterList = new ArrayList(); + List fieldInfoList = TypeUtils.computeGetters(clazz, aliasMap, false); + + for (FieldInfo fieldInfo : fieldInfoList) { + getterList.add(createFieldSerializer(fieldInfo)); + } + + getters = getterList.toArray(new FieldSerializer[getterList.size()]); + } + { + List getterList = new ArrayList(); + List fieldInfoList = TypeUtils.computeGetters(clazz, aliasMap, true); + + for (FieldInfo fieldInfo : fieldInfoList) { + getterList.add(createFieldSerializer(fieldInfo)); + } + + sortedGetters = getterList.toArray(new FieldSerializer[getterList.size()]); } - - // - getters = getterList.toArray(new FieldSerializer[getterList.size()]); - sortedGetters = getterList.toArray(new FieldSerializer[getterList.size()]); - Arrays.sort(sortedGetters); } protected boolean isWriteClassName(JSONSerializer serializer, Object obj, Type fieldType, Object fieldName) { diff --git a/src/main/java/com/alibaba/fastjson/serializer/SerializeWriter.java b/src/main/java/com/alibaba/fastjson/serializer/SerializeWriter.java index b4d49f17a..d038cc675 100644 --- a/src/main/java/com/alibaba/fastjson/serializer/SerializeWriter.java +++ b/src/main/java/com/alibaba/fastjson/serializer/SerializeWriter.java @@ -685,7 +685,7 @@ public final class SerializeWriter extends Writer { continue; } - if (CharTypes.isEmoji(ch)) { + if (ch >= 127) { lastSpecialIndex = i; newcount += 5; continue; @@ -728,7 +728,7 @@ public final class SerializeWriter extends Writer { continue; } - if (CharTypes.isEmoji(ch)) { + if (ch >= 127) { System.arraycopy(buf, i + 1, buf, i + 6, end - i - 1); buf[i] = '\\'; buf[i + 1] = 'u'; diff --git a/src/main/java/com/alibaba/fastjson/serializer/SerializerFeature.java b/src/main/java/com/alibaba/fastjson/serializer/SerializerFeature.java index ee38ba00f..72f4d526b 100644 --- a/src/main/java/com/alibaba/fastjson/serializer/SerializerFeature.java +++ b/src/main/java/com/alibaba/fastjson/serializer/SerializerFeature.java @@ -102,7 +102,12 @@ public enum SerializerFeature { /** * @since 1.1.19 */ - DisableCheckSpecialChar + DisableCheckSpecialChar, + + /** + * @since 1.1.20 + */ + NonDefault, ; private SerializerFeature(){ diff --git a/src/main/java/com/alibaba/fastjson/util/TypeUtils.java b/src/main/java/com/alibaba/fastjson/util/TypeUtils.java index 4c6b389ea..619eafa01 100644 --- a/src/main/java/com/alibaba/fastjson/util/TypeUtils.java +++ b/src/main/java/com/alibaba/fastjson/util/TypeUtils.java @@ -29,6 +29,7 @@ import java.math.BigInteger; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; +import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.Iterator; @@ -39,6 +40,7 @@ import java.util.Map; import com.alibaba.fastjson.JSONException; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.annotation.JSONField; +import com.alibaba.fastjson.annotation.JSONType; import com.alibaba.fastjson.parser.ParserConfig; import com.alibaba.fastjson.parser.deserializer.FieldDeserializer; @@ -749,10 +751,12 @@ public class TypeUtils { return clazz; } - - public static List computeGetters(Class clazz, Map aliasMap) { - List fieldInfoList = new ArrayList(); - + public static List computeGetters(Class clazz, + Map aliasMap) { + return computeGetters(clazz, aliasMap, true); + } + + public static List computeGetters(Class clazz, Map aliasMap, boolean sorted) { Map fieldInfoMap = new LinkedHashMap(); for (Method method : clazz.getMethods()) { @@ -885,8 +889,41 @@ public class TypeUtils { } } - for (FieldInfo fieldInfo : fieldInfoMap.values()) { - fieldInfoList.add(fieldInfo); + List fieldInfoList = new ArrayList(); + + boolean containsAll = false; + String[] orders = null; + + JSONType annotation = clazz.getAnnotation(JSONType.class); + if (annotation != null) { + orders = annotation.orders(); + + if (orders != null && orders.length == fieldInfoMap.size()) { + containsAll = true; + for (String item : orders) { + if (!fieldInfoMap.containsKey(item)) { + containsAll = false; + break; + } + } + } else { + containsAll = false; + } + } + + if (containsAll) { + for (String item : orders) { + FieldInfo fieldInfo = fieldInfoMap.get(item); + fieldInfoList.add(fieldInfo); + } + } else { + for (FieldInfo fieldInfo : fieldInfoMap.values()) { + fieldInfoList.add(fieldInfo); + } + + if (sorted) { + Collections.sort(fieldInfoList); + } } return fieldInfoList; diff --git a/src/test/java/com/alibaba/json/bvt/JSONTypeTest.java b/src/test/java/com/alibaba/json/bvt/JSONTypeTest.java new file mode 100644 index 000000000..11b0d5f2e --- /dev/null +++ b/src/test/java/com/alibaba/json/bvt/JSONTypeTest.java @@ -0,0 +1,132 @@ +package com.alibaba.json.bvt; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.annotation.JSONType; + +public class JSONTypeTest extends TestCase { + public void test_0() throws Exception { + VO vo = new VO(); + vo.setId(1001); + vo.setName("xx"); + vo.setAge(33); + + Assert.assertEquals("{\"age\":33,\"id\":1001,\"name\":\"xx\"}", + JSON.toJSONString(vo)); + } + + public void test_1() throws Exception { + V1 vo = new V1(); + vo.setId(1001); + vo.setName("xx"); + vo.setAge(33); + + Assert.assertEquals("{\"id\":1001,\"name\":\"xx\",\"age\":33}", + JSON.toJSONString(vo)); + } + + public void test_2() throws Exception { + V1 vo = new V1(); + vo.setId(1001); + vo.setName("xx"); + vo.setAge(33); + + Assert.assertEquals("{\"id\":1001,\"name\":\"xx\",\"age\":33}", + JSON.toJSONString(vo)); + } + + @JSONType + public static class VO { + private int id; + private String name; + private int age; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + } + + @JSONType(orders = { "id", "name", "age" }) + public static class V1 { + private int id; + private String name; + private int age; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + } + + @JSONType(orders = { "id", "name", "age" },asm=false) + private class V2 { + private int id; + private String name; + private int age; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + } +} diff --git a/src/test/java/com/alibaba/json/bvt/TestForEmoji.java b/src/test/java/com/alibaba/json/bvt/TestForEmoji.java index bcf9a7d12..44db296e1 100644 --- a/src/test/java/com/alibaba/json/bvt/TestForEmoji.java +++ b/src/test/java/com/alibaba/json/bvt/TestForEmoji.java @@ -21,4 +21,8 @@ public class TestForEmoji extends TestCase { Assert.assertEquals("\"\\uE001\"", JSON.toJSONString("\uE001", SerializerFeature.BrowserCompatible)); //E507 } + + public void test_zh() throws Exception { + Assert.assertEquals("\"\\u4E2D\\u56FD\"", JSON.toJSONString("中国", SerializerFeature.BrowserCompatible)); + } } diff --git a/src/test/java/com/alibaba/json/test/benchmark/BenchmarkTest.java b/src/test/java/com/alibaba/json/test/benchmark/BenchmarkTest.java index 362abe480..2d425522d 100644 --- a/src/test/java/com/alibaba/json/test/benchmark/BenchmarkTest.java +++ b/src/test/java/com/alibaba/json/test/benchmark/BenchmarkTest.java @@ -2,9 +2,8 @@ package com.alibaba.json.test.benchmark; import junit.framework.TestCase; -import com.alibaba.json.test.benchmark.encode.EishayEncode; +import com.alibaba.json.test.benchmark.decode.EishayDecode; import com.alibaba.json.test.codec.FastjsonCodec; -import com.alibaba.json.test.codec.JacksonCodec; public class BenchmarkTest extends TestCase { @@ -15,6 +14,7 @@ public class BenchmarkTest extends TestCase { executor.setExecuteCount(6); executor.getCodecList().add(new FastjsonCodec()); // executor.getCodecList().add(new JacksonCodec()); +// executor.getCodecList().add(new Jackson2Codec()); // // executor.getCodecList().add(new SimpleJsonCodec()); // executor.getCodecList().add(new JsonLibCodec()); @@ -24,10 +24,10 @@ public class BenchmarkTest extends TestCase { // executor.getCaseList().add(new EishayDecodeBytes()); // executor.getCaseList().add(new EishayDecode2Bytes()); -// executor.getCaseList().add(new EishayDecode()); + executor.getCaseList().add(new EishayDecode()); // executor.getCaseList().add(new EishayDecodeByClassName()); // executor.getCaseList().add(new EishayTreeDecode()); - executor.getCaseList().add(new EishayEncode()); +// executor.getCaseList().add(new EishayEncode()); // executor.getCaseList().add(new EishayEncodeManual()); // executor.getCaseList().add(new IntArray1000Decode()); // executor.getCaseList().add(new StringArray1000Decode()); diff --git a/src/test/java/com/alibaba/json/test/codec/Jackson2Codec.java b/src/test/java/com/alibaba/json/test/codec/Jackson2Codec.java new file mode 100644 index 000000000..c0e58ce9f --- /dev/null +++ b/src/test/java/com/alibaba/json/test/codec/Jackson2Codec.java @@ -0,0 +1,63 @@ +package com.alibaba.json.test.codec; + +import java.util.Collection; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; + + +public class Jackson2Codec implements Codec { + + private ObjectMapper mapper = new ObjectMapper(); + + public String getName() { + return "jackson2"; + } + + public final T decodeObject(String text, Class clazz) { + try { + return mapper.readValue(text, clazz); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + + public T decodeObject(byte[] input, Class clazz) throws Exception { + try { + return mapper.readValue(input, clazz); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + public Collection decodeArray(String text, Class clazz) throws Exception { + try { + return (Collection) mapper.readValue(text, new TypeReference() { + }); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + public final Object decodeObject(String text) { + try { + return (ObjectNode) mapper.readTree(text); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + public Object decode(String text) { + try { + return mapper.readTree(text); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + public String encode(Object object) throws Exception { + return mapper.writeValueAsString(object); + } +}