重写fastjson序列化方法实现自定义key&value

一个特殊需求,需要数据库实体对象转换成json的时候,key为数据库原表字段,value Date 转String,找了找博客,看了看fastjson的源码之后,决定重写JavaBeanSerializer 的 processKey 和 processValue 方法(这两个都是protected方法)

主要思路是解析mybatisplus 的 TableField 和 TableId 注解,转换key时碰到了个问题,由于早期的业务系统数据库命名不规范,无法通过Class.getDeclaredField(String name)直接获取该字段和对应注解信息,所以就只能获取所有字段然后一一进行字符小写比对,为了提高效率,定义了一个全局的静态ConcurrentHashMap作为缓存,这样一个Class就只需解析一次

EsJavaBeanSerializer.java

import com.alibaba.fastjson.serializer.*;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lvye.java.datacenter.common.annotation.LyAppendField;
import lvye.java.datacenter.common.utils.exception.BusinessException;

import java.lang.reflect.Field;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class  EsJavaBeanSerializer extends JavaBeanSerializer {

    public static volatile ConcurrentHashMap<String,String> fieldNameCache = new ConcurrentHashMap<String,String>()  ;

    private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");

    public EsJavaBeanSerializer(Class<?> beanType) {
        super(beanType);
    }

    public EsJavaBeanSerializer(Class<?> beanType, String... aliasList) {
        super(beanType, aliasList);
    }

    public EsJavaBeanSerializer(Class<?> beanType, Map<String, String> aliasMap) {
        super(beanType, aliasMap);
    }

    public EsJavaBeanSerializer(SerializeBeanInfo beanInfo) {
        super(beanInfo);
    }

    protected String processKey(JSONSerializer jsonBeanDeser, Object object, String key, Object propertyValue) {

        super.processKey(jsonBeanDeser, object, key, propertyValue);
        Class tempClass = object.getClass();
        if (tempClass != null) {
            try {
                if(fieldNameCache.containsKey(tempClass.toString().concat(key))){
                    key = fieldNameCache.get(tempClass.toString().concat(key));
                }else{
                    List<Field> fields = new ArrayList<>();
                    fields.addAll(Arrays.asList(tempClass.getDeclaredFields())) ;
                    fields.addAll(Arrays.asList(tempClass.getSuperclass().getDeclaredFields())) ;
                    for(Field field:fields){
                        if(key.toLowerCase().equals(field.getName().toLowerCase())){
                            if(field.isAnnotationPresent(LyAppendField.class)){
                                LyAppendField annotation = field.getAnnotation(LyAppendField.class);
                                return annotation.value();
                            }
                            else  if (field.isAnnotationPresent(TableId.class)) {
                                TableId annotation = field.getAnnotation(TableId.class);
                                return annotation.value();
                            } else if (field.isAnnotationPresent(TableField.class)) {
                                TableField annotation = field.getAnnotation(TableField.class);
                                return annotation.value();
                            }
                            fieldNameCache.putIfAbsent(tempClass.toString().concat(key),field.getName());
                            break ;
                        }
                    }


                }

            } catch (Exception e) {
                throw new BusinessException("序列化错误");
            }
        }
        return key;
    }

    protected Object processValue(JSONSerializer jsonBeanDeser, BeanContext beanContext, Object object, String key, Object propertyValue, int features) {
       Object value = super.processValue(jsonBeanDeser,beanContext,object,key,propertyValue,features);
       if(value != null){
           if(value instanceof Date){
               return formatDate((Date)value);
           }else if (value instanceof LocalDateTime){
               return formatLocalDateTime((LocalDateTime)value);
           }
       }
       return value;
    }


    public static String formatLocalDateTime(LocalDateTime date) {
        return formatter.format(date);
    }

    public static String formatDate(Date date) {
        Instant instant = date.toInstant();
        ZoneId zoneId = ZoneId.ofOffset("GMT", ZoneOffset.ofHours(8));
        LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
        return formatter.format(localDateTime);
    }


}

EsSerializerConfig.java

public class EsSerializerConfig  extends SerializeConfig {

    public ObjectSerializer getObjectWriter(Class<?> clazz) {
        ObjectSerializer writer = get(clazz);
        if(writer == null ){
            writer = new EsJavaBeanSerializer(clazz);
       }
        return writer;
    }

}

使用

JSON.toJSONString(esBaseDto, new EsSerializerConfig() , SerializerFeature.WriteMapNullValue)

实体类

@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("oms_order")
@LyKuduTable("presto::xxxxx.odsomsorder")
@LyEsIndex("order_oms_order")
public class OrderOmsOrder extends EsBaseDto<OrderOmsOrder> {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "订单id")
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    @ApiModelProperty(value = "公司id")
    @TableField("company_id")
    private Long companyId;

    @ApiModelProperty(value = "公司名称")
    @TableField("company_name")
    private String companyName;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容