@see https://github.com/alibaba/fastjson/issues/288
fastjson启用WriteClassName后,在android下,若javabean中定义了原生类型(long short double float short byte),
则系列化后json格式中将包含其对象类型的后缀(L S D F S B),导致parse时格式解析错误。
为了修复JavaBeanSerializer#createFieldSerializer,曲线救国,见代码:
/**
* @author zzf
*/
public class TObjectSerializer {
private static SerializeConfig serializeConfig = new SerializeConfig() {
/**
* private的变量,只能重新定义一把,开销不大。
*/
private ASMSerializerFactory asmFactory;
private boolean asm = !ASMUtils.isAndroid();
{
try {
asmFactory = new ASMSerializerFactory();
} catch (NoClassDefFoundError eror) {
asm = false;
} catch (ExceptionInInitializerError error) {
asm = false;
}
}
public ObjectSerializer createJavaBeanSerializer(Class<?> clazz) {
if (!Modifier.isPublic(clazz.getModifiers())) {
return new JavaBeanSerializerX(clazz);
}
boolean asm = this.asm;
if (asm && asmFactory.isExternalClass(clazz)
|| clazz == Serializable.class || clazz == Object.class) {
asm = false;
}
{
JSONType annotation = clazz.getAnnotation(JSONType.class);
if (annotation != null && annotation.asm() == false) {
asm = false;
}
}
if (asm && !ASMUtils.checkName(clazz.getName())) {
asm = false;
}
if (asm) {
try {
ObjectSerializer asmSerializer = createASMSerializer(clazz);
if (asmSerializer != null) {
return asmSerializer;
}
} catch (ClassCastException e) {
// skip
} catch (Throwable e) {
throw new JSONException(
"create asm serializer error, class " + clazz, e);
}
}
return new JavaBeanSerializerX(clazz);
}
class JavaBeanSerializerX extends JavaBeanSerializer {
public JavaBeanSerializerX(Class<?> clazz) {
super(clazz);
}
public FieldSerializer createFieldSerializer(FieldInfo fieldInfo) {
Class<?> clazz = fieldInfo.getFieldClass();
/**
* 修复android下的bug(非android下使用ASMSerializer,不报错)。
*
* 所有的努力都是为了这里,启用WriteClassName后,原生类型通过ObjectFieldSerializer(
* javabean反射)取得的值是对应的对象,json串会加上对应类型后缀(L、F、D、S、B)。
* 如果javabean使用原生类型定义变量,则反系列化parse时错误。
*
* 在此修复bug:原生类型务必使用NumberFieldSerializer
* (此类为包访问限制,只好复制一个NumberFieldSerializerX)
*
*/
if (clazz == Number.class || clazz == long.class || clazz == int.class
|| clazz == float.class || clazz == double.class
|| clazz == short.class || clazz == byte.class) {
return new NumberFieldSerializerX(fieldInfo);
}
return super.createFieldSerializer(fieldInfo);
}
}
/**
* copy NumberFieldSerializer
*/
class NumberFieldSerializerX extends FieldSerializer {
public NumberFieldSerializerX(FieldInfo fieldInfo) {
super(fieldInfo);
}
public void writeProperty(JSONSerializer serializer,
Object propertyValue) throws Exception {
writePrefix(serializer);
this.writeValue(serializer, propertyValue);
}
@Override
public void writeValue(JSONSerializer serializer,
Object propertyValue) throws Exception {
SerializeWriter out = serializer.getWriter();
Object value = propertyValue;
if (value == null) {
if (out.isEnabled(SerializerFeature.WriteNullNumberAsZero)) {
out.write('0');
} else {
out.writeNull();
}
return;
}
out.append(value.toString());
}
}
};
public static byte[] serializeJSON(Object obj) throws IOException {
return JSON.toJSONBytes(obj, serializeConfig,
SerializerFeature.WriteClassName);
}
public static Object deserializeJSON(byte[] data) throws IOException,
ClassNotFoundException {
return JSON.parse(data);
}
}