fast json详解三
SerializeFilter
SerializeFilter是通过编程扩展的方式定制序列化。fastjson支持6种SerializeFilter,用于不同场景的定制序列化。
- PropertyPreFilter 根据PropertyName判断是否序列化
- PropertyFilter 根据PropertyName和PropertyValue来判断是否序列化
- NameFilter 修改Key,如果需要修改Key,process返回值则可
- ValueFilter 修改Value
- BeforeFilter 序列化时在最前添加内容
- 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); } }
故乡明
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话