当前位置:   article > 正文

FastJSON指南_fastjson dependency

fastjson dependency

 

fastjson用于将Java Bean序列化为JSON字符串,也可以从JSON字符串反序列化到JavaBean。

简单使用

  • 通过maven引入相应的json包
  1. <dependencies>
  2. <dependency>
  3. <groupId>com.alibaba</groupId>
  4. <artifactId>fastjson</artifactId>
  5. <version>1.2.49</version>
  6. </dependency>
  7. </dependencies>
  • 定义一个需要转换所实体类User,代码如下:
  1. package com.ivan.json.entity;
  2. import java.util.Date;
  3. import com.alibaba.fastjson.annotation.JSONField;
  4. public class User {
  5. private Long id;
  6. private String name;
  7. @JSONField(format = "yyyy-MM-dd HH:mm:ss")
  8. private Date createTime;
  9. public Long getId() {
  10. return id;
  11. }
  12. public void setId(Long id) {
  13. this.id = id;
  14. }
  15. public String getName() {
  16. return name;
  17. }
  18. public void setName(String name) {
  19. this.name = name;
  20. }
  21. public Date getCreateTime() {
  22. return createTime;
  23. }
  24. public void setCreateTime(Date createTime) {
  25. this.createTime = createTime;
  26. }
  27. }
  • 写个简单的测试类用于测试fastjson的序列化与反序列化,代码如下:
  1. package com.ivan.json;
  2. import java.util.Date;
  3. import com.alibaba.fastjson.JSON;
  4. import com.ivan.json.entity.User;
  5. public class SimpleTest {
  6. public static void main(String[] args) {
  7. serialize();
  8. deserialize();
  9. }
  10. public static void serialize() {
  11. User user = new User();
  12. user.setId(11L);
  13. user.setName("西安");
  14. user.setCreateTime(new Date());
  15. String jsonString = JSON.toJSONString(user);
  16. System.out.println(jsonString);
  17. }
  18. public static void deserialize() {
  19. String jsonString = "{\"createTime\":\"2018-08-17 14:38:38\",\"id\":11,\"name\":\"西安\"}";
  20. User user = JSON.parseObject(jsonString, User.class);
  21. System.out.println(user.getName());
  22. System.out.println(user.getCreateTime());
  23. }
  24. }

SerializerFeature特性的使用

  fastjson通过SerializerFeature对生成的json格式的数据进行一些定制,比如可以输入的格式更好看,使用单引号而非双引号等。例子程序如下:

  1. package com.ivan.json;
  2. import java.util.Date;
  3. import com.alibaba.fastjson.JSON;
  4. import com.alibaba.fastjson.serializer.SerializerFeature;
  5. import com.ivan.json.entity.User;
  6. public class SerializerFeatureTest {
  7. public static void main(String[] args) {
  8. User user = new User();
  9. user.setId(11L);
  10. user.setCreateTime(new Date());
  11. String jsonString = JSON.toJSONString(user, SerializerFeature.PrettyFormat,
  12. SerializerFeature.WriteNullStringAsEmpty, SerializerFeature.UseSingleQuotes);
  13. System.out.println(jsonString);
  14. }
  15. }

 

 

输出的结果如下:

使用SerializerFeature的输出结果

 

SerializerFeature常用属性

名称含义
QuoteFieldNames输出key时是否使用双引号,默认为true
UseSingleQuotes使用单引号而不是双引号,默认为false
WriteMapNullValue是否输出值为null的字段,默认为false
WriteEnumUsingToStringEnum输出name()或者original,默认为false
UseISO8601DateFormatDate使用ISO8601格式输出,默认为false
WriteNullListAsEmptyList字段如果为null,输出为[],而非null
WriteNullStringAsEmpty字符类型字段如果为null,输出为”“,而非null
WriteNullNumberAsZero数值字段如果为null,输出为0,而非null
WriteNullBooleanAsFalseBoolean字段如果为null,输出为false,而非null
SkipTransientField如果是true,类中的Get方法对应的Field是transient,序列化时将会被忽略。默认为true
SortField按字段名称排序后输出。默认为false
WriteTabAsSpecial把\t做转义输出,默认为false不推荐设为true
PrettyFormat结果是否格式化,默认为false
WriteClassName序列化时写入类型信息,默认为false。反序列化是需用到
DisableCircularReferenceDetect消除对同一对象循环引用的问题,默认为false
WriteSlashAsSpecial对斜杠’/’进行转义
BrowserCompatible将中文都会序列化为\uXXXX格式,字节数会多一些,但是能兼容IE 6,默认为false
WriteDateUseDateFormat全局修改日期格式,默认为false。
DisableCheckSpecialChar一个对象的字符串属性中如果有特殊字符如双引号,将会在转成json时带有反斜杠转移符。如果不需要转义,可以使用这个属性。默认为false
BeanToArray将对象转为array输出

JSONField与JSONType注解的使用

  fastjson提供了JSONField对序列化与反序列化进行定制,比如可以指定字段的名称,序列化的顺序。JSONField用于属性,方法方法参数上。JSONField的源码如下:

  1. package com.alibaba.fastjson.annotation;
  2. import java.lang.annotation.ElementType;
  3. import java.lang.annotation.Retention;
  4. import java.lang.annotation.RetentionPolicy;
  5. import java.lang.annotation.Target;
  6. import com.alibaba.fastjson.parser.Feature;
  7. import com.alibaba.fastjson.serializer.SerializerFeature;
  8. @Retention(RetentionPolicy.RUNTIME)
  9. @Target({ ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER })
  10. public @interface JSONField {
  11. // 配置序列化和反序列化的顺序
  12. int ordinal() default 0;
  13. // 指定字段的名称
  14. String name() default "";
  15. // 指定字段的格式,对日期格式有用
  16. String format() default "";
  17. // 是否序列化
  18. boolean serialize() default true;
  19. // 是否反序列化
  20. boolean deserialize() default true;
  21. //字段级别的SerializerFeature
  22. SerializerFeature[] serialzeFeatures() default {};
  23. //
  24. Feature[] parseFeatures() default {};
  25. //给属性打上标签, 相当于给属性进行了分组
  26. String label() default "";
  27. boolean jsonDirect() default false;
  28. //制定属性的序列化类
  29. Class<?> serializeUsing() default Void.class;
  30. //制定属性的反序列化类
  31. Class<?> deserializeUsing() default Void.class;
  32. String[] alternateNames() default {};
  33. boolean unwrapped() default false;
  34. }

其中serializeUsing与deserializeUsing可以用于对字段的序列化与反序列化进行定制化。比如我们在User实体上加上个sex属性,类型为boolean。下面分别定义了序列化类与反序列化类,序列化类代码如下:

  1. package com.ivan.json.converter;
  2. import java.io.IOException;
  3. import java.lang.reflect.Type;
  4. import com.alibaba.fastjson.serializer.JSONSerializer;
  5. import com.alibaba.fastjson.serializer.ObjectSerializer;
  6. public class SexSerializer implements ObjectSerializer {
  7. public void write(JSONSerializer serializer,
  8. Object object,
  9. Object fieldName,
  10. Type fieldType,
  11. int features)
  12. throws IOException {
  13. Boolean value = (Boolean) object;
  14. String text = "女";
  15. if (value != null && value == true) {
  16. text = "男";
  17. }
  18. serializer.write(text);
  19. }
  20. }

反序列化类代码如下:

  1. package com.ivan.json.converter;
  2. import java.lang.reflect.Type;
  3. import com.alibaba.fastjson.parser.DefaultJSONParser;
  4. import com.alibaba.fastjson.parser.JSONToken;
  5. import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer;
  6. public class SexDeserialize implements ObjectDeserializer {
  7. public <T> T deserialze(DefaultJSONParser parser,
  8. Type type,
  9. Object fieldName) {
  10. String sex = parser.parseObject(String.class);
  11. if ("男".equals(sex)) {
  12. return (T) Boolean.TRUE;
  13. } else {
  14. return (T) Boolean.FALSE;
  15. }
  16. }
  17. public int getFastMatchToken() {
  18. return JSONToken.UNDEFINED;
  19. }
  20. }

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

  1. package com.alibaba.fastjson.annotation;
  2. import java.lang.annotation.ElementType;
  3. import java.lang.annotation.Retention;
  4. import java.lang.annotation.RetentionPolicy;
  5. import java.lang.annotation.Target;
  6. import com.alibaba.fastjson.PropertyNamingStrategy;
  7. import com.alibaba.fastjson.parser.Feature;
  8. import com.alibaba.fastjson.serializer.SerializeFilter;
  9. import com.alibaba.fastjson.serializer.SerializerFeature;
  10. @Retention(RetentionPolicy.RUNTIME)
  11. //需要标注在类上
  12. @Target({ ElementType.TYPE })
  13. public @interface JSONType {
  14. boolean asm() default true;
  15. //这里可以定义输出json的字段顺序
  16. String[] orders() default {};
  17. //包含的字段
  18. String[] includes() default {};
  19. //不包含的字段
  20. String[] ignores() default {};
  21. //类级别的序列化特性定义
  22. SerializerFeature[] serialzeFeatures() default {};
  23. Feature[] parseFeatures() default {};
  24. //按字母顺序进行输出
  25. boolean alphabetic() default true;
  26. Class<?> mappingTo() default Void.class;
  27. Class<?> builder() default Void.class;
  28. String typeName() default "";
  29. String typeKey() default "";
  30. Class<?>[] seeAlso() default{};
  31. //序列化类
  32. Class<?> serializer() default Void.class;
  33. //反序列化类
  34. Class<?> deserializer() default Void.class;
  35. boolean serializeEnumAsJavaBean() default false;
  36. PropertyNamingStrategy naming() default PropertyNamingStrategy.CamelCase;
  37. Class<? extends SerializeFilter>[] serialzeFilters() default {};
  38. }

SerializeFilter

fastjson通过SerializeFilter编程扩展的方式定制序列化fastjson支持以下SerializeFilter用于不同常景的定制序列化:

  • PropertyFilter 根据PropertyName和PropertyValue来判断是否序列化,接口定义如下:
  1. package com.alibaba.fastjson.serializer;
  2. /**
  3. * @author wenshao[szujobs@hotmail.com]
  4. */
  5. public interface PropertyFilter extends SerializeFilter {
  6. /**
  7. * @param object the owner of the property
  8. * @param name the name of the property
  9. * @param value the value of the property
  10. * @return true if the property will be included, false if to be filtered out
  11. * 根据 属性的name与value判断是否进行序列化
  12. */
  13. boolean apply(Object object, String name, Object value);
  14. }
  • PropertyPreFilter根据PropertyName判断是否序列化
  1. package com.alibaba.fastjson.serializer;
  2. public interface PropertyPreFilter extends SerializeFilter {
  3. //根据 object与name判断是否进行序列化
  4. boolean apply(JSONSerializer serializer, Object object, String name);
  5. }
  • NameFilter 序列化时修改Key
  1. package com.alibaba.fastjson.serializer;
  2. public interface NameFilter extends SerializeFilter {
  3. //根据 name与value的值,返回json字段key的值
  4. String process(Object object, String name, Object value);
  5. }
  • ValueFilter 序列化时修改Value
  1. package com.alibaba.fastjson.serializer;
  2. public interface ValueFilter extends SerializeFilter {
  3. //根据name与value定制输出json的value
  4. Object process(Object object, String name, Object value);
  5. }
  • BeforeFilter 在序列化对象的所有属性之前执行某些操作
  1. package com.alibaba.fastjson.serializer;
  2. public abstract class BeforeFilter implements SerializeFilter {
  3. private static final ThreadLocal<JSONSerializer> serializerLocal = new ThreadLocal<JSONSerializer>();
  4. private static final ThreadLocal<Character> seperatorLocal = new ThreadLocal<Character>();
  5. private final static Character COMMA = Character.valueOf(',');
  6. final char writeBefore(JSONSerializer serializer, Object object, char seperator) {
  7. serializerLocal.set(serializer);
  8. seperatorLocal.set(seperator);
  9. writeBefore(object);
  10. serializerLocal.set(null);
  11. return seperatorLocal.get();
  12. }
  13. protected final void writeKeyValue(String key, Object value) {
  14. JSONSerializer serializer = serializerLocal.get();
  15. char seperator = seperatorLocal.get();
  16. serializer.writeKeyValue(seperator, key, value);
  17. if (seperator != ',') {
  18. seperatorLocal.set(COMMA);
  19. }
  20. }
  21. //需要实现的方法,在实际实现中可以调用writeKeyValue增加json的内容
  22. public abstract void writeBefore(Object object);
  23. }
  • AfterFilter 在序列化对象的所有属性之后执行某些操作
  1. package com.alibaba.fastjson.serializer;
  2. /**
  3. * @since 1.1.35
  4. */
  5. public abstract class AfterFilter implements SerializeFilter {
  6. private static final ThreadLocal<JSONSerializer> serializerLocal = new ThreadLocal<JSONSerializer>();
  7. private static final ThreadLocal<Character> seperatorLocal = new ThreadLocal<Character>();
  8. private final static Character COMMA = Character.valueOf(',');
  9. final char writeAfter(JSONSerializer serializer, Object object, char seperator) {
  10. serializerLocal.set(serializer);
  11. seperatorLocal.set(seperator);
  12. writeAfter(object);
  13. serializerLocal.set(null);
  14. return seperatorLocal.get();
  15. }
  16. protected final void writeKeyValue(String key, Object value) {
  17. JSONSerializer serializer = serializerLocal.get();
  18. char seperator = seperatorLocal.get();
  19. serializer.writeKeyValue(seperator, key, value);
  20. if (seperator != ',') {
  21. seperatorLocal.set(COMMA);
  22. }
  23. }
  24. //子类需要实现的方法,实际使用的时候可以调用writeKeyValue增加内容
  25. public abstract void writeAfter(Object object);
  26. }
  • LabelFilter根据 JsonField配置的label来判断是否进行输出
  1. package com.alibaba.fastjson.serializer;
  2. //根据 JsonField配置的label来判断是否进行输出
  3. public interface LabelFilter extends SerializeFilter {
  4. boolean apply(String label);
  5. }

泛型反序列化

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

  1. package com.ivan.frame.dto.common;
  2. import java.io.Serializable;
  3. import com.alibaba.fastjson.JSONObject;
  4. public class BaseDTO implements Serializable{
  5. private static final long serialVersionUID = 2230553030766621644L;
  6. @Override
  7. public String toString() {
  8. return JSONObject.toJSONString(this);
  9. }
  10. }

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

  1. package com.ivan.frame.dto.common;
  2. public final class RequestDTO<T extends BaseDTO> extends BaseDTO {
  3. private static final long serialVersionUID = -2780042604928728379L;
  4. /**
  5. * 调用方的名称
  6. */
  7. private String caller;
  8. /**
  9. * 请求参数
  10. */
  11. private T param;
  12. public String getCaller() {
  13. return caller;
  14. }
  15. public void setCaller(String caller) {
  16. this.caller = caller;
  17. }
  18. /**
  19. * 获取请求参数
  20. */
  21. public T getParam() {
  22. return param;
  23. }
  24. /**
  25. * 设置请求参数
  26. *
  27. * @param param 请求参数
  28. */
  29. public void setParam(T param) {
  30. this.param = param;
  31. }
  32. }

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

  1. package com.ivan.frame.dto;
  2. import com.ivan.frame.dto.common.BaseDTO;
  3. public class PersonDTO extends BaseDTO {
  4. private static final long serialVersionUID = 4637634512292751986L;
  5. private int id;
  6. private int age;
  7. private String name;
  8. public int getId() {
  9. return id;
  10. }
  11. public void setId(int id) {
  12. this.id = id;
  13. }
  14. public int getAge() {
  15. return age;
  16. }
  17. public void setAge(int age) {
  18. this.age = age;
  19. }
  20. public String getName() {
  21. return name;
  22. }
  23. public void setName(String name) {
  24. this.name = name;
  25. }
  26. }

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

  1. package com.ivan.json;
  2. import com.alibaba.fastjson.JSON;
  3. import com.alibaba.fastjson.TypeReference;
  4. import com.ivan.frame.dto.PersonDTO;
  5. import com.ivan.frame.dto.common.RequestDTO;
  6. public class GenericTest {
  7. public static void main(String[] args) {
  8. RequestDTO<PersonDTO> requestDTO = new RequestDTO<PersonDTO>();
  9. requestDTO.setCaller("callerId");
  10. PersonDTO personDTO = new PersonDTO();
  11. personDTO.setAge(11);
  12. personDTO.setName("张三");
  13. requestDTO.setParam(personDTO);
  14. String jsonString = JSON.toJSONString(requestDTO);
  15. System.out.println(jsonString);
  16. //这行是关键代码
  17. requestDTO = JSON.parseObject(jsonString, new TypeReference<RequestDTO<PersonDTO>>(){});
  18. System.out.println(requestDTO.getParam().getName());
  19. }
  20. }

fastjson各种概念

  • JSON:本身是Abstract,提供了一系统的工具方法方便用户使用的API。

序列化相关的概念

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

反序列化相关的概念

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

与Spring MVC整合

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

  1. <mvc:annotation-driven conversion-service="conversionService">
  2. <mvc:message-converters register-defaults="true">
  3. <bean
  4. class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
  5. <property name="supportedMediaTypes">
  6. <list>
  7. <value>text/html;charset=UTF-8</value>
  8. <value>application/json;charset=UTF-8</value>
  9. </list>
  10. </property>
  11. <property name="features">
  12. <array>
  13. <value>WriteMapNullValue</value>
  14. <value>WriteNullStringAsEmpty</value>
  15. </array>
  16. </property>
  17. </bean>
  18. </mvc:message-converters>
  19. </mvc:annotation-driven>

这里有一个注意点,当你用Spring 3或者fastjson使用的是1.1.x的版本,在转换带有泛型参数类型的时候无法进行转换,而在Spring4配合fastjson1.2.X的版本可以解决这个问题。FastJsonHttpMessageConverter read的核心代码如下:

  1. public class FastJsonHttpMessageConverter extends AbstractHttpMessageConverter<Object>//
  2. implements GenericHttpMessageConverter<Object> {
  3. //将json转成javabean的时候会调用。这里的type
  4. public Object read(Type type, //
  5. Class<?> contextClass, //
  6. HttpInputMessage inputMessage //
  7. ) throws IOException, HttpMessageNotReadableException {
  8. return readType(getType(type, contextClass), inputMessage);
  9. }
  10. //这里会通过Spring4TypeResolvableHelper得到类型参数,
  11. protected Type getType(Type type, Class<?> contextClass) {
  12. if (Spring4TypeResolvableHelper.isSupport()) {
  13. return Spring4TypeResolvableHelper.getType(type, contextClass);
  14. }
  15. return type;
  16. }
  17. }

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/喵喵爱编程/article/detail/923079
推荐阅读
相关标签
  

闽ICP备14008679号