fastjson

fastjson是阿里巴巴的开源JSON解析库,它可以解析JSON格式的字符串,支持将Java Bean序列化为JSON字符串,也可以从JSON字符串反序列化到JavaBean。fastjson地址

引用

<!-- fastjson -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
</dependency>

下面例子中所使用的对象:

@Data
public class EmployeeVo implements Serializable {
    private Long id;
    private String name;
    private Short sex;
    private Date birthday;
    private String telephone;
    private BigDecimal salary;
    private Boolean isOfficial;
    private String hobby;

    public String getAbc() {
        return "abc方法";
    }
}

默认序列化(JSON.toJSONString)

    @Test
    public void serializeTest() {
        EmployeeVo employeeVo = new EmployeeVo();
        employeeVo.setId(1000L)
                .setName("haha")
                .setBirthday(new Date())
                .setSalary(new BigDecimal("19865.32"))
                .setIsOfficial(true)
                .setSex(new Short("0"))
                .setTelephone("021-2546589");
        String jsonStr = JSON.toJSONString(employeeVo);
        log.info(jsonStr);
    }

结果:

{"abc":"abc方法","birthday":1595037120123,"id":1000,"isOfficial":true,"name":"haha","salary":19865.32,"sex":0,"telephone":"021-2546589"}

默认反序列化(JSON.parseObject)

    @Test
    public void deserializeTest() {
        String jsonStr = "{\"abc\":\"abc方法\",\"birthday\":1592872441001,\"id\":1000,\"isOfficial\":true,\"name\":\"haha\",\"salary\":19865.32,\"sex\":0,\"telephone\":\"021-2546589\"}";
        EmployeeVo employeeVo = JSON.parseObject(jsonStr, EmployeeVo.class);
        log.info(employeeVo.toString());
    }

结果:EmployeeVo(id=1000, name=haha, sex=0, birthday=Tue Jun 23 08:34:01 CST 2020, telephone=021-2546589, salary=19865.32, isOfficial=true, hobby=null)


序列化个性化设置(SerializerFeature)

API接口:(JSON.toJSONString)

public static String toJSONString(Object object, SerializerFeature... features) {
     return toJSONString(object, DEFAULT_GENERATE_FEATURE, features);
}

常用的SerializerFeature在jar包中com.alibaba.fastjson.serializer.SerializerFeature枚举中都有定义,常用的有如配置:

  • SerializerFeature.SortField 按字段名称排序后输出,默认为false不排序
  • SerializerFeature.PrettyFormat 结果是否格式化,默认为false不格式化
  • SerializerFeature.WriteDateUseDateFormat 全局修改日期格式,默认为false不使用全局日期格式
  • SerializerFeature.WriteMapNullValue 将空值属性输出为null,默认空值属性不输出
  • SerializerFeature.WriteNullStringAsEmpty 将空值属性输出为“”(空字符串),默认空值属性不输出

序列化过滤器设置(SerializeFilter)

SerializeFilter可以序列化前和后做一些定制,如PropertyFilter,PropertyPreFilter,BeforeFilter,AfterFilter,LabelFilter,NameFilter,ValueFilter

  • PropertyFilter 根据PropertyName和PropertyValue来判断是否序列化,接口定义如下:

    public class SamplePropertyFilter implements PropertyFilter {
    
        /**
         * 根据 属性的name与value判断是否进行序列化
         *
         * @param object
         * @param name
         * @param value
         * @return
         */
        @Override
        public boolean apply(Object object, String name, Object value) {
            if("telephone".equals(name)){
               return false;
            }
            return true;
        }
    
    }
    
  • AfterFilter 在序列化对象的所有属性之后执行某些操作

    public class SampleAfterFilter extends AfterFilter {
        @Override
        public void writeAfter(Object object) {
            log.info("writeAfter==" + object);
        }
    }
    

使用:

    @Test
    public void propertyFilterTest() {
        EmployeeVo employeeVo = new EmployeeVo();
        employeeVo.setId(1000L).setName("haha").setBirthday(new Date()).setSalary(new BigDecimal("19865.32")).setIsOfficial(true).setSex(new Short("0")).setTelephone("021-2546589");
        SamplePropertyFilter samplePropertyFilter = new SamplePropertyFilter();
        SampleAfterFilter sampleAfterFilter = new SampleAfterFilter();
        String jsonStr1 = JSON.toJSONString(employeeVo, new SerializeFilter[]{samplePropertyFilter, sampleAfterFilter});
        // {"abc":"abc方法","birthday":1592873561942,"id":1000,"isOfficial":true,"name":"haha","salary":19865.32,"sex":0,"telephone":"021-2546589"}
        log.info(jsonStr1);
    }

自定义序列化、反序列化及@JSONField和@JSONType

  • 自定义的序列化

    // 将性别0和1序列化成“男”和“女”
    public class SexSerializer implements ObjectSerializer {
    
        @Override
        public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
            Short value = (Short) object;
            String text;
            if (value != null && value == 0) {
                text = "男";
            } else {
                text = "女";
            }
            serializer.write(text);
        }
    }
    
  • 自定义的反序列化

    // 将性别“男”和“女”反序列化成0和1
    public class SexDeserialize implements ObjectDeserializer {
    
        @Override
        public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
            String sex = parser.parseObject(String.class);
            if ("男".equals(sex)) {
                return (T) new Short("0");
            } else {
                return (T) new Short("1");
            }
    
        }
    
        @Override
        public int getFastMatchToken() {
            return 0;
        }
    }
    

    使用:配合@JSONField定义的属性上表示对该class适用

    @JSONField(serializeUsing = SexSerializer.class, deserializeUsing = SexDeserialize.class)
    private Short sex;
    
  • @JSONField,标注在属性上,部分配置如下:

    @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;
    }
    
  • @JSONType,标注在类上面

    @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 {};
    }
    

泛型反序列化(TypeReference)

泛型反序列化是指反序列化结果的对象是一个泛型,如ResponseVO<BaseVo>

public class ResponseVO<T extends BaseVo> {
    private int resultCode;
    private BaseVo resultData;
}

public class EmployeeVo extends BaseVo {
    // ...
}

如果对:{"resultCode":100,"resultData":{"abc":"abc方法","birthday":1595040655594,"id":1000,"isOfficial":true,"name":"haha","salary":19865.32,"sex":0,"telephone":"021-2546589"}} JSON串反序列化成ResponseVO<EmployeeVo>对象则需要:

ResponseVO<EmployeeVo> response = JSON.parseObject(jsonString, new TypeReference<ResponseVO<EmployeeVo>>(){});

综合API及相关概念

最全的JSON.toJSONString()方法:

public static String toJSONString(Object object, // 对象
                                  SerializeConfig config, // 配置并记录每种Java类型对应的序列化类
                                  SerializeFilter[] filters, // 序列化过滤器
                                  String dateFormat, // 日期的格式化
                                  int defaultFeatures, // 默认的格式化设置
                                  SerializerFeature... features) {// 对于对输出的json做各种格式化设置
    // ...
}
public static <T> T parseObject(String input, //json串
                                Type clazz, //对象clazz
                                ParserConfig config, //保存各种ObjectDeserializer
                                ParseProcess processor,//定制反序列化,类似于SerializeFilter
                                int featureValues,
                                Feature... features) {//反序列化的特性
    // ...
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342