FastJson小技巧——@JSONField

常见:使用fastjson进行需要对字段进行一些特殊处理,比如时间格式,前后端名字不一致,字段为null是否依然序列化等问题。那么fastjson的@JSONField就能很好的解决这些问题。

@JSONField注解的源码如下

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER })
public @interface JSONField {
  		int ordinal() default 0; //是根据fieldName的字母序进行序列的,你可以通过ordinal指定字段的顺序

        String name() default ""; //序列化和反序列化时候的别名

        String format() default ""; //用于字符串格式的日期转换

        boolean serialize() default true; // 是否参与序列化

        boolean deserialize() default true; //是否参与反序列化

        SerializerFeature[] serialzeFeatures() default {}; //序列化选项 SerializerFeature.WriteNullNumberAsZero 如空Number填充0

        Feature[] parseFeatures() default {}; //反序列化选项

        String label() default ""; //标签,

        boolean jsonDirect() default false; //当你有⼀个字段是json字符串的数据,你希望直接输出,⽽不是经过转义之后再输出。

        Class<?> serializeUsing() default Void.class; // 属性的序列化类,可定制。可有现存的,比如本来是Long,序列化的时候转为String:serializeUsing= ToStringSerializer.class

    	Class<?> deserializeUsing() default Void.class; // 属性的反序列化类,可定制。

    	String[] alternateNames() default {}; //参与反序列化时候的别名

        boolean unwrapped() default false; // 对象映射到父对象上。不进行子对象映射。简单而言,就是属性为对象的时候,属性对象里面的属性直接输出当做父对象的属性输出

        String defaultValue() default ""; //设置默认值
}

现在开始分别开始讲解如何使用:
1、ordinal 、name 、serialize、 deserialize、 format、defaultValue

public class JSONController {
    public static void main(String[] args) {
        Nation nationBean1 = Nation.builder().dress("现代服饰").num(1314).build();
        String str = JSON.toJSONString(nationBean1);
        System.out.println(str);                            //{"name":"汉族","number":1314}
        Nation nation = JSON.parseObject(str, Nation.class);
        System.out.println(JSON.toJSONString(nation));      //{"name":"汉族"}
    }
}

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
class Nation {
    @JSONField(defaultValue = "汉族")
    private String name;

    @JSONField(ordinal = 1, name = "DRESS", serialize = false)
    private String dress;

    @JSONField(ordinal = 2, name = "number", deserialize = false)
    private Integer num;

    @JSONField(ordinal = 3, format = "yyyy-MM-dd")
    private Date celebrateHoliday;
}

2、serialzeFeatures、parseFeatures
他们是序列化、反序列化时候的一些可选的特征:

序列化的时候
比如fastjson默认是不会将为null的属性输出的,若是我们也想输出,可以加入@JSONField(serialzeFeatures = SerializerFeature.WriteMapNullValue)。
还有就是,数值型为null的话,就输出0,可以使用@JSONField(serialzeFeatures = SerializerFeature.WriteNullNumberAsZero)

反序列化的时候,
比如parser是否将允许使用非双引号属性名字。@JSONField(parseFeatures = Feature.AllowSingleQuotes)

public class JSONController {
    public static void main(String[] args) {
        Nation nationBean1 = Nation.builder().name("汉族").build();
        String str = JSON.toJSONString(nationBean1);
        System.out.println(str);
        //{"celebrateHoliday":null,"name":"汉族","num":0}
    }
}

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
class Nation {
    private String name;
    private String dress;

    @JSONField(serialzeFeatures = SerializerFeature.WriteNullNumberAsZero)
    private Integer num;

    @JSONField(serialzeFeatures = SerializerFeature.WriteMapNullValue)
    private Date celebrateHoliday;
}

具体有:
名称 含义

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输出

3、label
可以给属性设置标签,这样可以批量处理某一类的属性,比如不序列化某一类属性。

public class JSONController {
    public static void main(String[] args) {
        Nation nationBean1 = Nation.builder().name("汉族").dress("便服").num(12).celebrateHoliday(new Date()).build();
        String str = JSON.toJSONString(nationBean1, Labels.includes("a"));
        System.out.println(str); //{"num":12}
        String str2 = JSON.toJSONString(nationBean1, Labels.excludes("a"));
        System.out.println(str2); //{"celebrateHoliday":1598929877786,"dress":"便服","name":"汉族"}
    }
}

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
class Nation {
    private String name;

    private String dress;

    @JSONField(label = "a")
    private Integer num;

    @JSONField(label = "b")
    private Date celebrateHoliday;
}

4、jsonDirect
它的作用是:当你有⼀个字段是json字符串的数据,你希望直接输出,而不是经过转义之后再输出。

public class JSONController {
    public static void main(String[] args) {
        Nation nationBean1 = Nation.builder().name("{}").dress("{}").build();
        String str = JSON.toJSONString(nationBean1);
        System.out.println(str); //{"dress":"{}","name":{}}

    }
}

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
class Nation {
    @JSONField(jsonDirect = true)
    private String name;
    @JSONField(jsonDirect = false)
    private String dress;
    private Integer num;
    private Date celebrateHoliday;
}


5、serializeUsing和deserializeUsing
可定制的序列化和反序列化的类,但是也有原生的。
比如原生:比如字段本来是Long,序列化的时候转为String。
比如自定义:我对某个字段加上我想要的处理结果“中国的”

public class JSONController {
    public static void main(String[] args) {
        Nation nationBean1 = Nation.builder().name("汉族").num(2323).build();
        String str = JSON.toJSONString(nationBean1);
        System.out.println(str);
        //{"name":"中国的汉族","num":"2323"}

    }

    public static class MySerializer implements ObjectSerializer {
        @Override
        public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
            String text = "中国的" + (String) object;
            serializer.write(text);
        }
    }
}

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
class Nation {
    @JSONField(serializeUsing = JSONController.MySerializer.class)
    private String name;
    private String dress;
    @JSONField(serializeUsing = ToStringSerializer.class)
    private Integer num;
    private Date celebrateHoliday;
}

6、alternateNames
反序列化时候的别名

public class JSONController {
    public static void main(String[] args) {
        String str ="{\"Name\":\"汉族\",\"num\":2323}";
        System.out.println(JSON.toJSONString(JSON.parseObject(str, Nation.class)));
        //{"name":"汉族","num":2323}
    }

}

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
class Nation {
    @JSONField(alternateNames = {"name", "Name"})
    private String name;
    private String dress;
    private Integer num;
    private Date celebrateHoliday;
}


7、unwrapped
对象映射到父对象上。不进行子对象映射。简单而言,就是属性为对象的时候,属性对象里面的属性直接输出当做父对象的属性输出

public class JSONController {
    public static void main(String[] args) {
        QSM qsm = new QSM();
        qsm.setName("传闻中的陈芊芊");
        qsm.setCity("花垣城");
        QSM qsm2 = new QSM();
        qsm2.setName("传闻中的韩烁");
        qsm2.setCity("玄虎城");

        Nation nation1 = Nation.builder().name("中国").qsm(qsm).qsm2(qsm2).build();
        System.out.println(JSON.toJSONString(nation1));
        //{"name":"中国","city":"花垣城","name":"传闻中的陈芊芊","qsm2":{"city":"玄虎城","name":"传闻中的韩烁"}}
    }

}

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
class Nation {
    private String name;

    @JSONField(unwrapped = true)
    private QSM qsm;

    @JSONField(unwrapped = false)
    private QSM qsm2;
}

@Data
class QSM {
    String name;
    String city;
}

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值