新增SerializerFeature.WriteEnumUsingName用于在序列化时输出枚举的name()值。

Release Notes(1.1.42) https://github.com/alibaba/fastjson/wiki/Release-Notes(1.1.42)  “修复序列化时SerializerFeature.WriteEnumUsingToString不生效的bug“,这种做法会引起问题。如果重写了枚举的toString方法,会导致反序列化失败。而且,此fix (https://github.com/alibaba/fastjson/commit/6a2b502455b54367cc2554eb5e00d27056c07f13)只修改了部分代码,还有几个地方在启用WriteEnumUsingToString特性时,仍然使用name()。

此修改序列化枚举时默认用枚举的name()值,和以前的版本保持一致,并且修改了所有使用WriteEnumUsingToString特性的代码,让他真正生效。
This commit is contained in:
邱占波
2015-03-01 02:02:13 +08:00
parent b21d6a5467
commit c4ee774635
6 changed files with 192 additions and 31 deletions
+1 -1
View File
@@ -88,7 +88,7 @@ public abstract class JSON implements JSONStreamAware, JSONAware {
int features = 0;
features |= SerializerFeature.QuoteFieldNames.getMask();
features |= SerializerFeature.SkipTransientField.getMask();
features |= SerializerFeature.WriteEnumUsingToString.getMask();
features |= SerializerFeature.WriteEnumUsingName.getMask();
features |= SerializerFeature.SortField.getMask();
// features |=
// com.alibaba.fastjson.serializer.SerializerFeature.WriteSlashAsSpecial.getMask();
@@ -32,11 +32,12 @@ public class EnumSerializer implements ObjectSerializer {
return;
}
if (serializer.isEnabled(SerializerFeature.WriteEnumUsingToString)) {
Enum<?> e = (Enum<?>) object;
Enum<?> e = (Enum<?>) object;
if(serializer.isEnabled(SerializerFeature.WriteEnumUsingName)){
serializer.write(e.name());
} else if (serializer.isEnabled(SerializerFeature.WriteEnumUsingToString)) {
serializer.write(e.toString());
} else {
Enum<?> e = (Enum<?>) object;
out.writeInt(e.ordinal());
}
}
@@ -15,11 +15,11 @@
*/
package com.alibaba.fastjson.serializer;
import java.util.Collection;
import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.fastjson.util.FieldInfo;
import java.util.Collection;
/**
* @author wenshao[szujobs@hotmail.com]
*/
@@ -31,6 +31,7 @@ public class ObjectFieldSerializer extends FieldSerializer {
boolean writeNullBooleanAsFalse = false;
boolean writeNullListAsEmpty = false;
boolean writeEnumUsingToString = false;
boolean writeEnumUsingName = false;
private RuntimeSerializerInfo runtimeInfo;
@@ -57,6 +58,8 @@ public class ObjectFieldSerializer extends FieldSerializer {
writeNullListAsEmpty = true;
} else if (feature == SerializerFeature.WriteEnumUsingToString) {
writeEnumUsingToString = true;
}else if(feature == SerializerFeature.WriteEnumUsingName){
writeEnumUsingName = true;
}
}
}
@@ -110,9 +113,15 @@ public class ObjectFieldSerializer extends FieldSerializer {
return;
}
if (writeEnumUsingToString == true && runtimeInfo.runtimeFieldClass.isEnum()) {
serializer.getWriter().writeString(((Enum<?>) propertyValue).name());
return;
if(runtimeInfo.runtimeFieldClass.isEnum()){
if(writeEnumUsingName){
serializer.getWriter().writeString(((Enum<?>) propertyValue).name());
return;
}
if(writeEnumUsingToString){
serializer.getWriter().writeString(((Enum<?>) propertyValue).toString());
return;
}
}
Class<?> valueClass = propertyValue.getClass();
@@ -115,6 +115,12 @@ public final class SerializeWriter extends Writer {
public void config(SerializerFeature feature, boolean state) {
if (state) {
features |= feature.getMask();
//由于枚举序列化特性WriteEnumUsingToString和WriteEnumUsingName不能共存,需要检查
if(feature == SerializerFeature.WriteEnumUsingToString){
features &= ~SerializerFeature.WriteEnumUsingName.getMask();
}else if(feature == SerializerFeature.WriteEnumUsingName){
features &= ~SerializerFeature.WriteEnumUsingToString.getMask();
}
} else {
features &= ~feature.getMask();
}
@@ -499,25 +505,34 @@ public final class SerializeWriter extends Writer {
return;
}
if (isEnabled(SerializerFeature.WriteEnumUsingToString)) {
if (isEnabled(SerializerFeature.UseSingleQuotes)) {
write('\'');
write(value.name());
write('\'');
write(c);
if (isEnabled(SerializerFeature.WriteEnumUsingName)) {
writeEnumValue(value.name(),c);
return;
}
} else {
write('\"');
write(value.name());
write('\"');
write(c);
}
if (isEnabled(SerializerFeature.WriteEnumUsingToString)) {
writeEnumValue(value.toString(),c);
return;
}
writeIntAndChar(value.ordinal(), c);
}
private void writeEnumValue(String value,char c){
if (isEnabled(SerializerFeature.UseSingleQuotes)) {
write('\'');
write(value);
write('\'');
write(c);
} else {
write('\"');
write(value);
write('\"');
write(c);
}
}
public void writeIntAndChar(int i, char c) {
if (i == Integer.MIN_VALUE) {
write("-2147483648");
@@ -1423,20 +1438,23 @@ public final class SerializeWriter extends Writer {
return;
}
if (isEnabled(SerializerFeature.WriteEnumUsingToString)) {
if (isEnabled(SerializerFeature.UseSingleQuotes)) {
writeFieldValue(seperator, name, value.name());
} else {
writeFieldValueStringWithDoubleQuote(seperator, name, value.name(), false);
return;
}
// writeStringWithDoubleQuote
if (isEnabled(SerializerFeature.WriteEnumUsingName)) {
writeEnumFieldValue(seperator,name,value.name());
}else if(isEnabled(SerializerFeature.WriteEnumUsingToString)){
writeEnumFieldValue(seperator,name,value.toString());
} else {
writeFieldValue(seperator, name, value.ordinal());
}
}
private void writeEnumFieldValue(char seperator,String name,String value){
if (isEnabled(SerializerFeature.UseSingleQuotes)) {
writeFieldValue(seperator, name, value);
} else {
writeFieldValueStringWithDoubleQuote(seperator, name, value, false);
}
}
public void writeFieldValue(char seperator, String name, BigDecimal value) {
write(seperator);
writeFieldName(name);
@@ -29,9 +29,13 @@ public enum SerializerFeature {
*/
WriteMapNullValue,
/**
*
* 用枚举toString()值输出
*/
WriteEnumUsingToString,
/**
* 用枚举name()输出
*/
WriteEnumUsingName,
/**
*
*/
@@ -0,0 +1,129 @@
/*
* www.yiji.com Inc.
* Copyright (c) 2014 All Rights Reserved
*/
/*
* 修订记录:
* qzhanbo@yiji.com 2015-03-01 00:55 创建
*
*/
package com.alibaba.json.bvt.serializer;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializeWriter;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.junit.Assert;
import org.junit.Test;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;
/**
* @author bohr.qiu@gmail.com
*/
public class EnumTest3 {
@Test
public void testDefault() throws Exception {
String json = JSON.toJSONString(Sex.M);
Assert.assertEquals(json, "\"M\"");
Pojo pojo = new Pojo();
pojo.setSex(Sex.M);
json = JSON.toJSONString(pojo);
Assert.assertEquals(json, "{\"sex\":\"M\"}");
try {
JSON.parseObject(json, Pojo.class);
Assert.assertTrue(true);
} catch (Exception e) {
Assert.fail("枚举默认序列化name值,可以反序列化成功");
}
Map<String, Pojo> map = new HashMap<String, Pojo>();
map.put("a", pojo);
json = JSON.toJSONString(map);
Assert.assertEquals(json, "{\"a\":{\"sex\":\"M\"}}");
Map<Sex, Pojo> enumMap = new EnumMap<Sex, Pojo>(Sex.class);
enumMap.put(Sex.M, pojo);
json = JSON.toJSONString(enumMap);
Assert.assertEquals(json, "{\"M\":{\"sex\":\"M\"}}");
}
@Test
public void testDefault1() throws Exception {
JSON.DUMP_CLASS = "/Users/bohr/Downloads/tmp";
String json = JSON.toJSONString(Sex.M, SerializerFeature.WriteEnumUsingToString);
Assert.assertEquals(json, "\"男\"");
Pojo pojo = new Pojo();
pojo.setSex(Sex.M);
json = JSON.toJSONString(pojo, SerializerFeature.WriteEnumUsingToString);
Assert.assertEquals(json, "{\"sex\":\"男\"}");
try {
JSON.parseObject(json, Pojo.class);
Assert.fail("toString的结果不能转换成枚举");
} catch (Exception e) {
Assert.assertTrue(true);
}
Map<String, Pojo> map = new HashMap<String, Pojo>();
map.put("a", pojo);
json = JSON.toJSONString(map, SerializerFeature.WriteEnumUsingToString);
Assert.assertEquals(json, "{\"a\":{\"sex\":\"男\"}}");
Map<Sex, Pojo> enumMap = new EnumMap<Sex, Pojo>(Sex.class);
enumMap.put(Sex.M, pojo);
json = JSON.toJSONString(enumMap, SerializerFeature.WriteEnumUsingToString);
Assert.assertEquals(json, "{\"男\":{\"sex\":\"男\"}}");
}
@Test
public void testName() throws Exception {
Assert.assertEquals("\"男\"", JSON.toJSONString(Sex.M, SerializerFeature.WriteEnumUsingToString));
Assert.assertEquals("\"女\"", JSON.toJSONString(Sex.W, SerializerFeature.WriteEnumUsingToString));
}
@Test
public void testWriterSerializerFeature() throws Exception {
SerializeWriter writer=new SerializeWriter();
writer.config(SerializerFeature.WriteEnumUsingToString,true);
Assert.assertTrue(writer.isEnabled(SerializerFeature.WriteEnumUsingToString));
writer.config(SerializerFeature.WriteEnumUsingName,true);
Assert.assertTrue(writer.isEnabled(SerializerFeature.WriteEnumUsingName));
Assert.assertFalse(writer.isEnabled(SerializerFeature.WriteEnumUsingToString));
writer.config(SerializerFeature.WriteEnumUsingToString,true);
Assert.assertTrue(writer.isEnabled(SerializerFeature.WriteEnumUsingToString));
Assert.assertFalse(writer.isEnabled(SerializerFeature.WriteEnumUsingName));
}
public static enum Sex {
M("男"),
W("女");
private String msg;
Sex(String msg) {
this.msg = msg;
}
@Override
public String toString() {
return msg;
}
}
public static class Pojo {
private Sex sex;
public Sex getSex() {
return sex;
}
public void setSex(Sex sex) {
this.sex = sex;
}
}
}