修复fastjson启用WriteClassName时parse原生类型属性错误的bug

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



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值