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