重寫fastjson序列化方法實現(xiàn)自定義key&value

一個特殊需求,需要數(shù)據(jù)庫實體對象轉(zhuǎn)換成json的時候,key為數(shù)據(jù)庫原表字段,value Date 轉(zhuǎn)String,找了找博客,看了看fastjson的源碼之后,決定重寫JavaBeanSerializer 的 processKey 和 processValue 方法(這兩個都是protected方法)

主要思路是解析mybatisplus 的 TableField 和 TableId 注解,轉(zhuǎn)換key時碰到了個問題,由于早期的業(yè)務系統(tǒng)數(shù)據(jù)庫命名不規(guī)范,無法通過Class.getDeclaredField(String name)直接獲取該字段和對應注解信息,所以就只能獲取所有字段然后一一進行字符小寫比對,為了提高效率,定義了一個全局的靜態(tài)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;
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容