fast json详解三

SerializeFilter

SerializeFilter是通过编程扩展的方式定制序列化。fastjson支持6种SerializeFilter,用于不同场景的定制序列化。

  1. PropertyPreFilter 根据PropertyName判断是否序列化
  2. PropertyFilter 根据PropertyName和PropertyValue来判断是否序列化
  3. NameFilter 修改Key,如果需要修改Key,process返回值则可
  4. ValueFilter 修改Value
  5. BeforeFilter 序列化时在最前添加内容
  6. AfterFilter 序列化时在最后添加内容
  • PropertyFilter 根据PropertyName和PropertyValue来判断是否序列化
  public interface PropertyFilter extends SerializeFilter {
      boolean apply(Object object, String propertyName, Object propertyValue);
  }

可以通过扩展实现根据object或者属性名称或者属性值进行判断是否需要序列化。例如:

    PropertyFilter filter = new PropertyFilter() {

        public boolean apply(Object source, String name, Object value) {
            if ("id".equals(name)) {
                int id = ((Integer) value).intValue();
                return id >= 100;
            }
            return false;
        }
    };
    
    JSON.toJSONString(obj, filter); // 序列化的时候传入filter
  • PropertyPreFilter 根据PropertyName判断是否序列化
和PropertyFilter不同只根据object和name进行判断,在调用getter之前,这样避免了getter调用可能存在的异常。

 public interface PropertyPreFilter extends SerializeFilter {
      boolean apply(JSONSerializer serializer, Object object, String name);
  }

实例

String json = "{"store":{"book":[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99}],"bicycle":{"color":"red","price":19.95}},"expensive":10}";
SimplePropertyPreFilter filter = new SimplePropertyPreFilter();
filter.getExcludes().add("price");
JSONObject jsonObject = JSON.parseObject(json);
String str = JSON.toJSONString(jsonObject, filter);
System.out.println(str);
public void test_0() throws Exception {
    class VO {
        public int getId() { throw new RuntimeException(); }
    }

    PropertyPreFilter filter = new PropertyPreFilter () {
        public boolean apply(JSONSerializer serializer, Object source, String name) {
            return false;
        }
    };

    VO vo = new VO();

    String text = JSON.toJSONString(vo, filter);
    Assert.assertEquals("{}", text);
}
  • NameFilter 序列化时修改Key
public interface NameFilter extends SerializeFilter {
    String process(Object object, String propertyName, Object propertyValue);
}

实例

@Test
public void givenSerializeConfig_whenJavaObject_thanJsonCorrect() {
    NameFilter formatName = new NameFilter() {
        public String process(Object object, String name, Object value) {
            return name.toLowerCase().replace(" ", "_");
        }
    };
     
    SerializeConfig.getGlobalInstance().addFilter(Person.class,  formatName);
    String jsonOutput =
      JSON.toJSONStringWithDateFormat(listOfPersons, "yyyy-MM-dd");
}
  • ValueFilter 序列化时修改Value
public interface ValueFilter extends SerializeFilter {
      Object process(Object object, String propertyName, Object propertyValue);
  }

实例

ValueFilter filter =new ValueFilter() {
@Override
    public Objectprocess(Object object, String name, Object value) {
        String idKey ="id";
        if(idKey.equals(name)) {
                return value.toString();
        }
        return value;
    }
};
return JSONObject.toJSONString(result, filter);
  • BeforeFilter 序列化时在最前添加内容
public abstract class BeforeFilter implements SerializeFilter {
      protected final void writeKeyValue(String key, Object value) { ... }
      // 需要实现的抽象方法,在实现中调用writeKeyValue添加内容
      public abstract void writeBefore(Object object);
  }
  • AfterFilter 序列化时在最后添加内容

 public abstract class AfterFilter implements SerializeFilter {
      protected final void writeKeyValue(String key, Object value) { ... }
      // 需要实现的抽象方法,在实现中调用writeKeyValue添加内容
      public abstract void writeAfter(Object object);
  }

全部实例代码

package com.itheima.fastjson.config;

import com.alibaba.fastjson.serializer.*;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 配置fastjson转换器 默认是jackson
 */
@Configuration
public class FastjsonConverConfig {


    @Bean
    public HttpMessageConverters httpMessageConverters(){
        FastJsonHttpMessageConverter fastJsonConverter = new FastJsonHttpMessageConverter();
        // 设置支持的MediaType
        List<MediaType> typeList = new ArrayList<>();
        typeList.add(MediaType.APPLICATION_JSON_UTF8); // APPLICATION_JSON_UTF8的将来被获取的值是application/json;charset=UTF-8
        fastJsonConverter.setSupportedMediaTypes(typeList);

        // 设置fastjson的全局配置(谨慎使用)
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        fastJsonConfig.setCharset(Charset.forName("UTF-8"));
        // 配置SerializerFeature - 为了数据序列化的格式化处理
        fastJsonConfig.setSerializerFeatures(
                SerializerFeature.DisableCircularReferenceDetect,
                SerializerFeature.WriteMapNullValue,
                SerializerFeature.WriteNullStringAsEmpty
        );
        // 配置SerializeConfig 能够制定具体类型使用的序列化转换器
        SerializeConfig serializeConfig = new SerializeConfig();
        serializeConfig.put(Date.class,new SimpleDateFormatSerializer("yyyy-MM-dd HH:mm:ss")); //类似设定全局日期转换
        // 模拟上面的序列化配置 自定义BigDecimal序列化器
        // 问题:当IdCard类中没有@JSONField注解并且没有format属性时,下面的这个配置不执行
//        serializeConfig.put(BigDecimal.class,new MyBigDecimalSerializer(2)); //类似设定全局日期转换
        fastJsonConfig.setSerializeConfig(serializeConfig);

        // 属性过滤器 after过滤器
        /*PropertyFilter propertyFilter = new PropertyFilter() {
            @Override
            public boolean apply(Object object, String name, Object value) {
                // BigDecimal类型的 不进行序列化;后面使用BeforeFilter/AfterFilter手动填充
                if(value instanceof BigDecimal)
                    return false;
                return true;
            }
        };
        AfterFilter afterFilter = new AfterFilter() {
            @Override
            public void writeAfter(Object object) {
                Field[] fields = object.getClass().getDeclaredFields();
                for (Field field : fields) {
                    if (field.getType() == BigDecimal.class) {
                        field.setAccessible(true);
                        Object value= null;
                        try {
                            value = (BigDecimal)field.get(object);
                            value = ((BigDecimal) value).setScale(2,BigDecimal.ROUND_DOWN);
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                        // 将key value写入到序列化的字符串中
                        writeKeyValue(field.getName(), value );
                    }
                }
            }
        };*/
//        fastJsonConfig.setSerializeFilters(propertyFilter,afterFilter);
        ValueFilter valueFilter = new ValueFilter() {
            @Override
            public Object process(Object object, String name, Object value) {
                if(value instanceof BigDecimal){
                    value = ((BigDecimal)value).setScale(3,BigDecimal.ROUND_DOWN);
                }
                return value;
            }
        };
        fastJsonConfig.setSerializeFilters(valueFilter);
        fastJsonConverter.setFastJsonConfig(fastJsonConfig);
        return new HttpMessageConverters(fastJsonConverter);
    }

}
package com.itheima.fastjson.config;

import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.ObjectSerializer;

import java.io.IOException;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 *
 */
public class MyBigDecimalSerializer implements ObjectSerializer {

    public final Integer newScale;

    public MyBigDecimalSerializer(Integer newScale) {
        this.newScale = newScale;
    }

    @Override
    public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
        if(object == null){
            serializer.out.write("0.00");
            return;
        }
        serializer.out.write(((BigDecimal)object).setScale(newScale,RoundingMode.DOWN).toString());;
    }
}
package com.itheima.fastjson.pojo;

import com.alibaba.fastjson.annotation.JSONField;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.math.BigDecimal;
import java.util.Date;

@Data
@NoArgsConstructor
@AllArgsConstructor
// 银行卡
public class IdCard {

    private String cardNo;
//    @JSONField(format = "yyyy/MM/dd") // 实际生效在getter setter上
    private Date birthday;
    private BigDecimal balance;
}
package com.itheima.fastjson.pojo;

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

import java.util.ArrayList;
import java.util.List;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private Integer id;
    private String username;
    private List<IdCard> idCards = new ArrayList<IdCard>();
}
package com.itheima.fastjson.controller;

import com.itheima.fastjson.pojo.IdCard;
import com.itheima.fastjson.pojo.User;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

/**
 *
 */
@RestController
public class DemoController {
    @RequestMapping("/user/{id}")
    public User findUserById(@PathVariable Integer id){

        List<IdCard> idCardList = new ArrayList<>();
        Calendar instance = Calendar.getInstance();
        instance.set(1990,10,10,10,10,10);
        IdCard card1 = new IdCard("1001",instance.getTime(),new BigDecimal("100.015"));
        idCardList.add(card1);
        instance.set(2000,9,9,9,9,9);
        IdCard card2 = new IdCard("1002",instance.getTime(),new BigDecimal("300.0123"));
        idCardList.add(card2);

        return new User(1,null,idCardList);
    }
}
故乡明
原文地址:https://www.cnblogs.com/luweiweicode/p/14084162.html