zoukankan      html  css  js  c++  java
  • fast json详解二

    • 通过maven引入相应的json包
        <dependencies>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.49</version>
            </dependency>
        </dependencies>
    • 定义一个需要转换所实体类User,代码如下:
    package com.ivan.json.entity;
    
    import java.util.Date;
    
    import com.alibaba.fastjson.annotation.JSONField;
    
    public class User {
    
        private Long   id;
    
        private String name;
    
        @JSONField(format = "yyyy-MM-dd HH:mm:ss")
        private Date   createTime;
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Date getCreateTime() {
            return createTime;
        }
    
        public void setCreateTime(Date createTime) {
            this.createTime = createTime;
        }
        
    }
    View Code
    1. 写个简单的测试类用于测试fastjson的序列化与反序列化,代码如下:
    package com.ivan.json;
    
    import java.util.Date;
    
    import com.alibaba.fastjson.JSON;
    import com.ivan.json.entity.User;
    
    public class SimpleTest {
    
        public static void main(String[] args) {
            serialize();
            deserialize();
        }
    
        public static void serialize() {
            User user = new User();
            user.setId(11L);
            user.setName("西安");
            user.setCreateTime(new Date());
            String jsonString = JSON.toJSONString(user);
            System.out.println(jsonString);
        }
    
        public static void deserialize() {
            String jsonString = "{"createTime":"2018-08-17 14:38:38","id":11,"name":"西安"}";
            User user = JSON.parseObject(jsonString, User.class);
            System.out.println(user.getName());
            System.out.println(user.getCreateTime());
        }
    }
    View Code
    • fastjson通过SerializerFeature对生成的json格式的数据进行一些定制,比如可以输入的格式更好看,使用单引号而非双引号等。例子程序如下:
    package com.ivan.json;
    
    import java.util.Date;
    
    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.serializer.SerializerFeature;
    import com.ivan.json.entity.User;
    
    public class SerializerFeatureTest {
    
        public static void main(String[] args) {
            User user = new User();
            user.setId(11L);
            user.setCreateTime(new Date());
            String jsonString = JSON.toJSONString(user, SerializerFeature.PrettyFormat, 
                    SerializerFeature.WriteNullStringAsEmpty, SerializerFeature.UseSingleQuotes);
            System.out.println(jsonString);
    
        }
    
    }
    View Code
    • SerializerFeature常用属性

    • JSONField与JSONType注解的使用

    package com.alibaba.fastjson.annotation;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    import com.alibaba.fastjson.parser.Feature;
    import com.alibaba.fastjson.serializer.SerializerFeature;
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER })
    public @interface JSONField {
    // 配置序列化和反序列化的顺序
        int ordinal() default 0;
    // 指定字段的名称
        String name() default "";
    // 指定字段的格式,对日期格式有用
        String format() default "";
     // 是否序列化
        boolean serialize() default true;
    // 是否反序列化
        boolean deserialize() default true;
    //字段级别的SerializerFeature
        SerializerFeature[] serialzeFeatures() default {};
    //
        Feature[] parseFeatures() default {};
       //给属性打上标签, 相当于给属性进行了分组
        String label() default "";
        
        boolean jsonDirect() default false;
        
    //制定属性的序列化类
        Class<?> serializeUsing() default Void.class;
     //制定属性的反序列化类
        Class<?> deserializeUsing() default Void.class;
    
        String[] alternateNames() default {};
    
        boolean unwrapped() default false;
    }
    View Code
    其中serializeUsing与deserializeUsing可以用于对字段的序列化与反序列化进行定制化。比如我们在User实体上加上个sex属性,类型为boolean。下面分别定义了序列化类与反序列化类,序列化类代码如下:
    package com.ivan.json.converter;
    
    import java.io.IOException;
    import java.lang.reflect.Type;
    
    import com.alibaba.fastjson.serializer.JSONSerializer;
    import com.alibaba.fastjson.serializer.ObjectSerializer;
    
    public class SexSerializer implements ObjectSerializer {
    
        public void write(JSONSerializer serializer,
                          Object object,
                          Object fieldName,
                          Type fieldType,
                          int features)
                throws IOException {
            Boolean value = (Boolean) object;
            String text = "女";
            if (value != null && value == true) {
                text = "男";
            }
            serializer.write(text);
        }
    
    }
    View Code

     反序列化类代码如下:

    package com.ivan.json.converter;
    
    import java.lang.reflect.Type;
    
    
    import com.alibaba.fastjson.parser.DefaultJSONParser;
    import com.alibaba.fastjson.parser.JSONToken;
    import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer;
    
    public class SexDeserialize implements ObjectDeserializer {
    
        public <T> T deserialze(DefaultJSONParser parser,
                                            Type type,
                                            Object fieldName) {
            
    
    
            String sex = parser.parseObject(String.class);
            if ("男".equals(sex)) {
                return (T) Boolean.TRUE;
            } else {
                return (T) Boolean.FALSE;
            }
        }
    
        public int getFastMatchToken() {
            return JSONToken.UNDEFINED;
        }
    
    }
    View Code

    fastjosn提供了JSONType用于类级别的定制化, JSONType的源码如下:

    package com.alibaba.fastjson.annotation;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    import com.alibaba.fastjson.PropertyNamingStrategy;
    import com.alibaba.fastjson.parser.Feature;
    import com.alibaba.fastjson.serializer.SerializeFilter;
    import com.alibaba.fastjson.serializer.SerializerFeature;
    
    @Retention(RetentionPolicy.RUNTIME)
    //需要标注在类上
    @Target({ ElementType.TYPE })
    public @interface JSONType {
    
        boolean asm() default true;
    //这里可以定义输出json的字段顺序
        String[] orders() default {};
    //包含的字段
        String[] includes() default {};
    //不包含的字段
        String[] ignores() default {};
    //类级别的序列化特性定义
        SerializerFeature[] serialzeFeatures() default {};
        Feature[] parseFeatures() default {};
        //按字母顺序进行输出
        boolean alphabetic() default true;
        
        Class<?> mappingTo() default Void.class;
        
        Class<?> builder() default Void.class;
        
        String typeName() default "";
    
        String typeKey() default "";
        
        Class<?>[] seeAlso() default{};
        //序列化类
        Class<?> serializer() default Void.class;
        //反序列化类
        Class<?> deserializer() default Void.class;
    
        boolean serializeEnumAsJavaBean() default false;
    
        PropertyNamingStrategy naming() default PropertyNamingStrategy.CamelCase;
    
        Class<? extends SerializeFilter>[] serialzeFilters() default {};
    }
    View Code
    • PropertyFilter 根据PropertyName和PropertyValue来判断是否序列化,接口定义如下:
    package com.alibaba.fastjson.serializer;
    
    /**
     * @author wenshao[szujobs@hotmail.com]
     */
    public interface PropertyFilter extends SerializeFilter {
    
        /**
         * @param object the owner of the property
         * @param name the name of the property
         * @param value the value of the property
         * @return true if the property will be included, false if to be filtered out
        * 根据 属性的name与value判断是否进行序列化
         */
        boolean apply(Object object, String name, Object value);
    }
    View Code
    • PropertyPreFilter根据PropertyName判断是否序列化
    package com.alibaba.fastjson.serializer;
    
    public interface PropertyPreFilter extends SerializeFilter {
    
    //根据 object与name判断是否进行序列化
        boolean apply(JSONSerializer serializer, Object object, String name);
    }
    View Code
    • NameFilter 序列化时修改Key
    package com.alibaba.fastjson.serializer;
    
    public interface NameFilter extends SerializeFilter {
    //根据 name与value的值,返回json字段key的值
        String process(Object object, String name, Object value);
    }
    View Code
    • ValueFilter 序列化时修改Value
    package com.alibaba.fastjson.serializer;
    
    public interface ValueFilter extends SerializeFilter {
      //根据name与value定制输出json的value
        Object process(Object object, String name, Object value);
    }
    View Code
    • BeforeFilter 在序列化对象的所有属性之前执行某些操作
    package com.alibaba.fastjson.serializer;
    
    public abstract class BeforeFilter implements SerializeFilter {
    
        private static final ThreadLocal<JSONSerializer> serializerLocal = new ThreadLocal<JSONSerializer>();
        private static final ThreadLocal<Character>      seperatorLocal  = new ThreadLocal<Character>();
    
        private final static Character                   COMMA           = Character.valueOf(',');
    
        final char writeBefore(JSONSerializer serializer, Object object, char seperator) {
            serializerLocal.set(serializer);
            seperatorLocal.set(seperator);
            writeBefore(object);
            serializerLocal.set(null);
            return seperatorLocal.get();
        }
    
        protected final void writeKeyValue(String key, Object value) {
            JSONSerializer serializer = serializerLocal.get();
            char seperator = seperatorLocal.get();
            serializer.writeKeyValue(seperator, key, value);
            if (seperator != ',') {
                seperatorLocal.set(COMMA);
            }
        }
    //需要实现的方法,在实际实现中可以调用writeKeyValue增加json的内容
        public abstract void writeBefore(Object object);
    }
    View Code
    • AfterFilter 在序列化对象的所有属性之后执行某些操作
    package com.alibaba.fastjson.serializer;
    
    /**
     * @since 1.1.35
     */
    public abstract class AfterFilter implements SerializeFilter {
    
        private static final ThreadLocal<JSONSerializer> serializerLocal = new ThreadLocal<JSONSerializer>();
        private static final ThreadLocal<Character>      seperatorLocal  = new ThreadLocal<Character>();
    
        private final static Character                   COMMA           = Character.valueOf(',');
    
        final char writeAfter(JSONSerializer serializer, Object object, char seperator) {
            serializerLocal.set(serializer);
            seperatorLocal.set(seperator);
            writeAfter(object);
            serializerLocal.set(null);
            return seperatorLocal.get();
        }
    
        protected final void writeKeyValue(String key, Object value) {
            JSONSerializer serializer = serializerLocal.get();
            char seperator = seperatorLocal.get();
            serializer.writeKeyValue(seperator, key, value);
            if (seperator != ',') {
                seperatorLocal.set(COMMA);
            }
        }
    //子类需要实现的方法,实际使用的时候可以调用writeKeyValue增加内容
        public abstract void writeAfter(Object object);
    }
    View Code
    • LabelFilter根据 JsonField配置的label来判断是否进行输出
    package com.alibaba.fastjson.serializer;
    
    //根据 JsonField配置的label来判断是否进行输出
    public interface LabelFilter extends SerializeFilter {
        boolean apply(String label);
    }
    View Code

    泛型反序列化

    fastjson通过TypeReference来实现泛型的反序列化,以下是一个简单的例子程序。首先定义了BaseDTO用于所有DTO的父类,代码如下:

    package com.ivan.frame.dto.common;
    
    import java.io.Serializable;
    
    import com.alibaba.fastjson.JSONObject;
    
    public class BaseDTO implements Serializable{
    
        private static final long  serialVersionUID = 2230553030766621644L;
    
        @Override
        public String toString() {
            return JSONObject.toJSONString(this);
        }
    
    }
    View Code

    RequestDTO用于抽像所有的请求DTO,里面有个泛型参数,代码如下:

    package com.ivan.frame.dto.common;
    
    
    public final class RequestDTO<T extends BaseDTO> extends BaseDTO {
    
        private static final long serialVersionUID = -2780042604928728379L;
    
        /**
         * 调用方的名称
         */
        private String            caller;
    
        /**
         * 请求参数
         */
        private T                 param;
        
    
     
        public String getCaller() {
            return caller;
        }
    
        public void setCaller(String caller) {
            this.caller = caller;
        }
    
        /**
         * 获取请求参数
         */
        public T getParam() {
            return param;
        }
    
        /**
         * 设置请求参数
         * 
         * @param param 请求参数
         */
        public void setParam(T param) {
            this.param = param;
        }
    
    }
    View Code

    定义一个具体的业务对象, PersonDTO代码如下:

    package com.ivan.frame.dto;
    
    import com.ivan.frame.dto.common.BaseDTO;
    
    public class PersonDTO extends BaseDTO {
        
        private static final long serialVersionUID = 4637634512292751986L;
        
        private int id;
        private int age;
        private String name;
        
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        
    }
    View Code

    通过JSON.parseObject传入TypeReference对象进行泛型转换,代码如下:

    package com.ivan.json;
    
    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.TypeReference;
    import com.ivan.frame.dto.PersonDTO;
    import com.ivan.frame.dto.common.RequestDTO;
    
    public class GenericTest {
    
        public static void main(String[] args) {
            RequestDTO<PersonDTO> requestDTO = new RequestDTO<PersonDTO>();
            requestDTO.setCaller("callerId");
            PersonDTO personDTO = new PersonDTO();
            personDTO.setAge(11);
            personDTO.setName("张三");
            requestDTO.setParam(personDTO);
            
            String jsonString = JSON.toJSONString(requestDTO);
            System.out.println(jsonString);
            //这行是关键代码
            requestDTO = JSON.parseObject(jsonString, new TypeReference<RequestDTO<PersonDTO>>(){});
            
            
            System.out.println(requestDTO.getParam().getName());
        }
    }
    View Code

    fastjson各种概念

    • SerializeConfig:内部是个map容器主要功能是配置并记录每种Java类型对应的序列化类。
    • SerializeWriter 继承自Java的Writer,其实就是个转为FastJSON而生的StringBuilder,完成高性能的字符串拼接。
    • SerializeFilter: 用于对对象的序列化实现各种定制化的需求。
    • SerializerFeature:对于对输出的json做各种格式化的需求。
    • JSONSerializer:相当于一个序列化组合器,集成了SerializeConfig, SerializeWriter , SerializeFilter与SerializerFeature。
    序列化的入口代码如下,上面提到的各种概念都包含了
        public static String toJSONString(Object object, // 
                                          SerializeConfig config, // 
                                          SerializeFilter[] filters, // 
                                          String dateFormat, //
                                          int defaultFeatures, // 
                                          SerializerFeature... features) {
            SerializeWriter out = new SerializeWriter(null, defaultFeatures, features);
    
            try {
                JSONSerializer serializer = new JSONSerializer(out, config);
                
                if (dateFormat != null && dateFormat.length() != 0) {
                    serializer.setDateFormat(dateFormat);
                    serializer.config(SerializerFeature.WriteDateUseDateFormat, true);
                }
    
                if (filters != null) {
                    for (SerializeFilter filter : filters) {
                        serializer.addFilter(filter);
                    }
                }
    
                serializer.write(object);
    
                return out.toString();
            } finally {
                out.close();
            }
        }
    View Code

     反序列化相关的概念

    • ParserConfig:内部通过一个map保存各种ObjectDeserializer。
    • JSONLexer : 与SerializeWriter相对应,用于解析json字符串。
    • JSONToken:定义了一系统的特殊字符,这些称为token。
    • ParseProcess :定制反序列化,类似于SerializeFilter。
    • Feature:用于定制各种反序列化的特性。
    • DefaultJSONParser:相当于反序列化组合器,集成了ParserConfig,Feature, JSONLexer 与ParseProcess。
    反序列化的入口代码如下,上面的概念基本都包含了:
        @SuppressWarnings("unchecked")
        public static <T> T parseObject(String input, Type clazz, ParserConfig config, ParseProcess processor,
                                              int featureValues, Feature... features) {
            if (input == null) {
                return null;
            }
    
            if (features != null) {
                for (Feature feature : features) {
                    featureValues |= feature.mask;
                }
            }
    
            DefaultJSONParser parser = new DefaultJSONParser(input, config, featureValues);
    
            if (processor != null) {
                if (processor instanceof ExtraTypeProvider) {
                    parser.getExtraTypeProviders().add((ExtraTypeProvider) processor);
                }
    
                if (processor instanceof ExtraProcessor) {
                    parser.getExtraProcessors().add((ExtraProcessor) processor);
                }
    
                if (processor instanceof FieldTypeResolver) {
                    parser.setFieldTypeResolver((FieldTypeResolver) processor);
                }
            }
    
            T value = (T) parser.parseObject(clazz, null);
    
            parser.handleResovleTask(value);
    
            parser.close();
    
            return (T) value;
        }
    View Code

     与Spring MVC整合

    fastjson提供了FastJsonHttpMessageConverter用于将Spring mvc里的body数据(必须是json格式)转成Controller里的请求参数或者将输出的对象转成json格式的数据。spring mvc里的核心配置如下:

        <mvc:annotation-driven conversion-service="conversionService">
            <mvc:message-converters register-defaults="true">
                <bean
                    class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
                    <property name="supportedMediaTypes">
                        <list>
                            <value>text/html;charset=UTF-8</value>
                            <value>application/json;charset=UTF-8</value>
                        </list>
                    </property>
                    <property name="features">
                        <array>
                            <value>WriteMapNullValue</value>
                            <value>WriteNullStringAsEmpty</value>
                        </array>
                    </property>
                </bean>
            </mvc:message-converters>
        </mvc:annotation-driven>
    View Code
    这里有一个注意点,当你用Spring 3或者fastjson使用的是1.1.x的版本,在转换带有泛型参数类型的时候无法进行转换,而在Spring4配合fastjson1.2.X的版本可以解决这个问题。FastJsonHttpMessageConverter read的核心代码如下:

    public class FastJsonHttpMessageConverter extends AbstractHttpMessageConverter<Object>//
            implements GenericHttpMessageConverter<Object> {
    
    //将json转成javabean的时候会调用。这里的type
        public Object read(Type type, //
                           Class<?> contextClass, //
                           HttpInputMessage inputMessage //
        ) throws IOException, HttpMessageNotReadableException {
            return readType(getType(type, contextClass), inputMessage);
        }
    
    //这里会通过Spring4TypeResolvableHelper得到类型参数,
        protected Type getType(Type type, Class<?> contextClass) {
            if (Spring4TypeResolvableHelper.isSupport()) {
                return Spring4TypeResolvableHelper.getType(type, contextClass);
            }
    
            return type;
        }
    
    }
    View Code
    故乡明
  • 相关阅读:
    初识python 2.x与3.x 区别
    装饰器
    函数的进阶
    Spring Boot启动问题:Cannot determine embedded database driver class for database type NONE
    22.Spring Cloud Config安全保护
    23.Spring Cloud Bus 无法更新问题(踩坑) Spring cloud config server Could not fetch remote for master remote
    24.Spring Cloud之Spring Cloud Config及Spring Cloud Bus
    Spring Boot整合Spring Data Elasticsearch 踩坑
    项目中Spring Security 整合Spring Session实现记住我功能
    32.再谈SpringBoot文件上传
  • 原文地址:https://www.cnblogs.com/luweiweicode/p/14084073.html
Copyright © 2011-2022 走看看