zoukankan      html  css  js  c++  java
  • 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);
        }
    }
    故乡明
  • 相关阅读:
    16个最棒的jQuery视差滚动效果教程
    16个最棒的WordPress婚纱摄影网站主题
    2013年最受欢迎的16个HTML5 WordPress主题
    16个最佳PSD文件下载网站
    16个最热门的 Android Apps 推荐下载
    前端工程师应该都了解的16个最受欢迎的CSS框架
    16个最好并且实用的jQuery插件【TheTop16.com】
    16个最受欢迎的Magento电子商务主题【TheTop16.com】
    [Nunit] System.Net.Sockets.SocketException : An existing connection was forcibly closed by the remote host
    WORD
  • 原文地址:https://www.cnblogs.com/luweiweicode/p/14084162.html
Copyright © 2011-2022 走看看