Spring Boot 使用FastJson反序列化自定义属性的时间格式

#问题的由来
由于前端传的日期格式比较奇葩 (eg:09-13/2018),如果是以此方式到后台通过@ResquestBody 注解的接收话会报序列化错误。

解决办法

在要进行反序列化的实体类上添加注解@JSONField(deserializeUsing=DateExtraProcessor.class),其中DateExtraProcessor就是自定义的反序列化处理类。

import java.io.Serializable;
import java.util.Date;

import com.alibaba.fastjson.annotation.JSONField;
import com.quanquantech.company.config.DateExtraProcessor;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;


@NoArgsConstructor
@AllArgsConstructor
@Data
public class Article implements Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = -633397330272103911L;
	private int id;
	private int news_type;
	private String intro_img;
	private String content;
	@JSONField(deserializeUsing=DateExtraProcessor.class)
	private Date time;
	private String title;
	private String describe;

}
import java.lang.reflect.Type;
import java.util.Date;
import java.util.Map;

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.DefaultJSONParser;
import com.alibaba.fastjson.parser.JSONToken;
import com.alibaba.fastjson.parser.deserializer.AbstractDateDeserializer;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class DateExtraProcessor extends AbstractDateDeserializer {

	private   DateTimeFormatter pattern = DateTimeFormat.forPattern("MM-dd/yyyy");
	
	@Override
	protected  T cast(DefaultJSONParser parser, Type clazz, Object fieldName, Object value) {
		Object object = parser.input;//此处得到是前端传来的所有数据的原始格式字符串
		
		Map map = JSON.parseObject(String.valueOf(object),Map.class);//将json字符串转为map,方便后续操作
		
		String timestr =(String) map.get(String.valueOf(fieldName));//获取对应参数值(ps:不明白参数类型为什么是Object)
		if(log.isDebugEnabled()){
			log.debug("time is  {}",timestr);
		}
		
		Date date = parseStr2Date(timestr);//格式化成日期
		return (T)date;
	}

	private  Date parseStr2Date(String source) {
		return DateTime.parse(source, pattern).toDate();//使用joda的日期操作类
	}
		
	@Override
	public int getFastMatchToken() {
		
		return JSONToken.LITERAL_STRING;
	}

}

关于AbstractDateDeserializer这个类,我一开始也不知道,是通过看JSON 这个类的源码看到ParserConfig这个核心序列化的处理类中定义了多个序列化处理类

		 private final IdentityHashMap deserializers         = new IdentityHashMap();
		 
        deserializers.put(SimpleDateFormat.class, MiscCodec.instance);
        deserializers.put(java.sql.Timestamp.class, SqlDateDeserializer.instance_timestamp);
        deserializers.put(java.sql.Date.class, SqlDateDeserializer.instance);
        deserializers.put(java.sql.Time.class, TimeDeserializer.instance);
        deserializers.put(java.util.Date.class, DateCodec.instance);
        deserializers.put(Calendar.class, CalendarCodec.instance);
        deserializers.put(XMLGregorianCalendar.class, CalendarCodec.instance);

        deserializers.put(JSONObject.class, MapDeserializer.instance);
        deserializers.put(JSONArray.class, CollectionCodec.instance);

        deserializers.put(Map.class, MapDeserializer.instance);
        deserializers.put(HashMap.class, MapDeserializer.instance);
        deserializers.put(LinkedHashMap.class, MapDeserializer.instance);
        deserializers.put(TreeMap.class, MapDeserializer.instance);
        deserializers.put(ConcurrentMap.class, MapDeserializer.instance);
        deserializers.put(ConcurrentHashMap.class, MapDeserializer.instance);

        deserializers.put(Collection.class, CollectionCodec.instance);
        deserializers.put(List.class, CollectionCodec.instance);
        deserializers.put(ArrayList.class, CollectionCodec.instance);

        deserializers.put(Object.class, JavaObjectDeserializer.instance);
        deserializers.put(String.class, StringCodec.instance);
        deserializers.put(StringBuffer.class, StringCodec.instance);
        deserializers.put(StringBuilder.class, StringCodec.instance);
        deserializers.put(char.class, CharacterCodec.instance);
        deserializers.put(Character.class, CharacterCodec.instance);
        deserializers.put(byte.class, NumberDeserializer.instance);
        deserializers.put(Byte.class, NumberDeserializer.instance);
        deserializers.put(short.class, NumberDeserializer.instance);
        deserializers.put(Short.class, NumberDeserializer.instance);
        deserializers.put(int.class, IntegerCodec.instance);
        deserializers.put(Integer.class, IntegerCodec.instance);
        deserializers.put(long.class, LongCodec.instance);
        deserializers.put(Long.class, LongCodec.instance);
        deserializers.put(BigInteger.class, BigIntegerCodec.instance);
        deserializers.put(BigDecimal.class, BigDecimalCodec.instance);
        deserializers.put(float.class, FloatCodec.instance);
        deserializers.put(Float.class, FloatCodec.instance);
        deserializers.put(double.class, NumberDeserializer.instance);
        deserializers.put(Double.class, NumberDeserializer.instance);
        deserializers.put(boolean.class, BooleanCodec.instance);
        deserializers.put(Boolean.class, BooleanCodec.instance);
        deserializers.put(Class.class, MiscCodec.instance);
        deserializers.put(char[].class, new CharArrayCodec());

        deserializers.put(AtomicBoolean.class, BooleanCodec.instance);
        deserializers.put(AtomicInteger.class, IntegerCodec.instance);
        deserializers.put(AtomicLong.class, LongCodec.instance);
        deserializers.put(AtomicReference.class, ReferenceCodec.instance);

        deserializers.put(WeakReference.class, ReferenceCodec.instance);
        deserializers.put(SoftReference.class, ReferenceCodec.instance);

        deserializers.put(UUID.class, MiscCodec.instance);
        deserializers.put(TimeZone.class, MiscCodec.instance);
        deserializers.put(Locale.class, MiscCodec.instance);
        deserializers.put(Currency.class, MiscCodec.instance);
        deserializers.put(InetAddress.class, MiscCodec.instance);
        deserializers.put(Inet4Address.class, MiscCodec.instance);
        deserializers.put(Inet6Address.class, MiscCodec.instance);
        deserializers.put(InetSocketAddress.class, MiscCodec.instance);
        deserializers.put(File.class, MiscCodec.instance);
        deserializers.put(URI.class, MiscCodec.instance);
        deserializers.put(URL.class, MiscCodec.instance);
        deserializers.put(Pattern.class, MiscCodec.instance);
        deserializers.put(Charset.class, MiscCodec.instance);
        deserializers.put(JSONPath.class, MiscCodec.instance);
        deserializers.put(Number.class, NumberDeserializer.instance);
        deserializers.put(AtomicIntegerArray.class, AtomicCodec.instance);
        deserializers.put(AtomicLongArray.class, AtomicCodec.instance);
        deserializers.put(StackTraceElement.class, StackTraceElementDeserializer.instance);

        deserializers.put(Serializable.class, JavaObjectDeserializer.instance);
        deserializers.put(Cloneable.class, JavaObjectDeserializer.instance);
        deserializers.put(Comparable.class, JavaObjectDeserializer.instance);
        deserializers.put(Closeable.class, JavaObjectDeserializer.instance);

        deserializers.put(JSONPObject.class, new JSONPDeserializer());

这些自定义的处理类都实现了ObjectDeserializer接口,由此我在com.alibaba.fastjson.parser.deserializer这个包下看到了一些和反序列化相关的核心处理类,AbstractDateDeserializer此类就在其中。(ps:不得不吐槽下fastjson的文档写的真烂, 而且很多类都没介绍)

你可能感兴趣的:(java开发)