搭建单体SpringBoot项目 集成FastJson json数据处理
1. 集成 Fastjson 简单使用
1 2 3 4 5 6 7 <dependencies > <dependency > <groupId > com.alibaba</groupId > <artifactId > fastjson</artifactId > <version > 1.2.49</version > </dependency > </dependencies >
2. fastjson - 自定义序列化
序列化时需要进行特殊处理的类型 ,可以进行特殊配置。
2.1. 自定义反序列化解析器 - ObjectSerializer 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 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 { serializer.write(text); } }
2.2. 使用解析器 有三种方法,按情况决定使用哪种。
定义的字段上加解析器注解
1 2 3 4 5 6 @Setter @Getter private static class ResultData { @JSONField(serializeUsing = SexSerializer.class) private Sex sex; }
框架统一配置 ,序列化时会根据类型进行匹配。
在WebAppConfigurer#configureMessageConverters中加入。
1 SerializeConfig.getGlobalInstance().put(AlarmString.class,AlarmStringSerializer.instance);
系列化时使用。
1 2 3 SerializeConfig config = new SerializeConfig ();config.put(AlarmString.class,AlarmStringSerializer.instance); String jsonStr = JSON.toJsonString(alarm, config);
2.3. 序列化相关的概念
SerializeConfig:内部是个map容器主要功能是配置并记录每种Java类型对应的序列化类。
SerializeWriter 继承自Java的Writer,其实就是个转为FastJSON而生的StringBuilder,完成高性能的字符串拼接。
SerializeFilter: 用于对对象的序列化实现各种定制化的需求。
SerializerFeature:对于对输出的json做各种格式化的需求。
JSONSerializer:相当于一个序列化组合器,集成了SerializeConfig, SerializeWriter , SerializeFilter与SerializerFeature。
序列化的入口代码如下,上面提到的各种概念都包含了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 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(); } }
3. fastjson - 自定义反序列化
反序列化时需要进行特殊处理的类型 ,可以进行特殊配置。
3.1. 自定义反序列化解析器 - ObjectDeserializer 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class PersonDeserializer implements ObjectDeserializer { @Override public Person deserialze (DefaultJSONParser parser, Type type, Object fieldName) { return null ; } @Override public int getFastMatchToken () { return 0 ; } }
3.2. 使用解析器 有三种方法,按情况决定使用哪种。
定义的字段上加解析器注解
1 2 3 4 5 6 @Setter @Getter private static class ResultData { @JSONField(deserializeUsing = PersonDeserializer.class) private Person personInfo; }
框架统一配置 ,反序列化时会根据类型进行匹配。
在WebAppConfigurer#configureMessageConverters中加入。
1 ParserConfig.getGlobalInstance().putDeserializer(AlarmString.class,AlarmStringDeserializer.instance);
反系列化时使用。
1 2 3 ParserConfig parserConfig = new ParserConfig ();parserConfig.putDeserializer(AlarmString.class, AlarmStringDeserializer.instance); Alarm alarm = JSON.parseObject(jsonStr, Alarm.class, parserConfig);
3.2.1. 反序列化相关的概念
ParserConfig:内部通过一个map保存各种ObjectDeserializer。
JSONLexer : 与SerializeWriter相对应,用于解析json字符串。
JSONToken:定义了一系统的特殊字符,这些称为token。
ParseProcess :定制反序列化,类似于SerializeFilter。
Feature:用于定制各种反序列化的特性。
DefaultJSONParser:相当于反序列化组合器,集成了ParserConfig,Feature, JSONLexer 与ParseProcess。
反序列化的入口代码如下,上面的概念基本都包含了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 @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; }
4. JSONField与JSONType注解的使用 4.1. @JSONField fastjson提供了JSONField对序列化与反序列化进行定制,比如可以指定字段的名称,序列化的顺序。JSONField用于属性,方法方法参数上。JSONField的源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 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[] 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 ; }
4.2. @JSONType fastjosn提供了JSONType用于类级别的定制化, JSONType的源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 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 ; 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 {}; }
5. SerializeFilter fastjson通过SerializeFilter编程扩展的方式定制序列化fastjson支持以下SerializeFilter用于不同常景的定制序列化:
PropertyFilter 根据PropertyName和PropertyValue来判断是否序列化,接口定义如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 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); }
PropertyPreFilter根据PropertyName判断是否序列化
1 2 3 4 5 6 7 package com.alibaba.fastjson.serializer; public interface PropertyPreFilter extends SerializeFilter { //根据 object与name判断是否进行序列化 boolean apply(JSONSerializer serializer, Object object, String name); }
1 2 3 4 5 6 package com.alibaba.fastjson.serializer; public interface NameFilter extends SerializeFilter { //根据 name与value的值,返回json字段key的值 String process(Object object, String name, Object value); }
1 2 3 4 5 6 package com.alibaba.fastjson.serializer; public interface ValueFilter extends SerializeFilter { //根据name与value定制输出json的value Object process(Object object, String name, Object value); }
BeforeFilter 在序列化对象的所有属性之前执行某些操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 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); }
AfterFilter 在序列化对象的所有属性之后执行某些操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 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); }
LabelFilter根据 JsonField配置的label来判断是否进行输出
1 2 3 4 5 6 package com.alibaba.fastjson.serializer; //根据 JsonField配置的label来判断是否进行输出 public interface LabelFilter extends SerializeFilter { boolean apply(String label); }
6. Fastjson - SerializerFeature特性的使用 fastjson通过SerializerFeature对生成的json格式的数据进行一些定制,比如可以输入的格式更好看,使用单引号而非双引号等。例子程序如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 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); } }
输出的结果如下:
1 2 3 4 5 { 'createTime': '2021 -06 -23 15 : 17 : 48 ', 'id': 123 'name': '' }
SerializerFeature常用属性
名称
含义
QuoteFieldNames
输出key时是否使用双引号,默认为true
UseSingleQuotes
使用单引号而不是双引号,默认为false
WriteMapNullValue
是否输出值为null的字段,默认为false
WriteEnumUsingToString
Enum输出name()或者original,默认为false
UseISO8601DateFormat
Date使用ISO8601格式输出,默认为false
WriteNullListAsEmpty
List字段如果为null,输出为[],而非null
WriteNullStringAsEmpty
字符类型字段如果为null,输出为”“,而非null
WriteNullNumberAsZero
数值字段如果为null,输出为0,而非null
WriteNullBooleanAsFalse
Boolean字段如果为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输出