@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); } }