第⼀章JacksonUtil序列化与反序列化属性总结
1.json-lib与Jackson
  关于json-lib与Jackson对⽐总结如下:
  1).性能⽅⾯,Jackson的处理能⼒⾼出Json-lib10倍左右。
  2).json-lib已经停⽌更新,最新的版本也是基于JDK1.5,⽽Jackson的社区则较为活跃。
  3).json-lib依赖commons系列的包及 ezmorph包共 5个,⽽Jackson除⾃⾝的以外只依赖于commons-logging
2.1 Jackson序列化与反序列化⽅法
1  public static String encode(Object obj) {
2        try {
3            return objectMapper.writeValueAsString(obj);
4        } catch (Exception e) {
5            ("jackson encode error:", e);
6        }
7        return null;
8    }
9
10    /**
11      * 将json string反序列化成对象
12      *
13      * @param json
14      * @param valueType
15      * @return
16      */
17    public static <T> T decode(String json, Class<T> valueType) {
18        try {
19            adValue(json, valueType);
20        } catch (Exception e) {
21            ("jackson decode(String, Class<T>) error: ", e);
22        }
23        return null;
24    }
25
26    /**
27      * 将json array反序列化为对象
28      *
29      * @param json
30      * @param typeReference
31      * @return
32      */
33    public static <T> T decode(String json, TypeReference<T> typeReference) {
34        try {
35            return (T) adValue(json, typeReference);
36        } catch (Exception e) {
37            ("decode(String, JsonTypeReference<T>)", e);
38        }
39        return null;
40    }
View Code
2.2 Jackson⾃动检测机制
  jackson默认的字段属性发现规则如下:
    所有被public修饰的字段->所有被public修饰的getter->所有被public修饰的setter
  若类中的⼀个private属性,且没有设置public的getter和setter⽅法,则对该类对象进⾏序列化时,默认不对这个private属性进⾏序列化。  若此时任然需要对该private属性进⾏序列化,可以通过设置⾃动检测功能来实现:
  2.2.1 通过配置属性实现fastjson常用方法
1 objectMapper
2            .setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY) // ⾃动检测所有类的全部属性
3            .setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.ANY) //⾃动检测所有类的public getter⽅法
4        .setVisibility(PropertyAccessor.IS_GETTER, JsonAutoDetect.Visibility.ANY); //⾃动检测所有类的public setter⽅法
View Code
  2.2.2 使⽤@JsonAutoDetect(作⽤在类上)来开启/禁⽌⾃动检测 
    fieldVisibility:字段的可见级别
    ANY:任何级别的字段都可以⾃动识别
    NONE:所有字段都不可以⾃动识别
    NON_PRIVATE:⾮private修饰的字段可以⾃动识别
    PROTECTED_AND_PUBLIC:被protected和public修饰的字段可以被⾃动识别
    PUBLIC_ONLY:只有被public修饰的字段才可以被⾃动识别
    DEFAULT:同PUBLIC_ONLY
  @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
3.序列化与反序列化属性总结
  与json-lib相⽐,Jackson在序列化与反序列时,可以对序列化与反序列化进⾏配置,是的输出结果满⾜⾃⼰的要求。序列化与反序列化属性很多,下⾯对⼀些常⽤属性进⾏介绍。
  3.1 序列化属性 
//这个特性,决定了解析器是否将⾃动关闭那些不属于parser⾃⼰的输⼊源。
// 如果禁⽌,则调⽤应⽤不得不分别去关闭那些被⽤来创建parser的基础输⼊流InputStream和reader;
//默认是true
//是否允许解析使⽤Java/C++ 样式的注释(包括'/'+'*' 和'//' 变量)
//设置为true时,属性名称不带双引号
//反序列化是是否允许属性名称不带双引号
//是否允许单引号来包住属性名称和字符串值
//是否允许JSON字符串包含⾮引号控制字符(值⼩于32的ASCII字符,包含制表符和换⾏符)
//是否允许JSON整数以多个0开始
//null的属性不序列化
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
//按字母顺序排序属性,默认false
//是否以类名作为根元素,可以通过@JsonRootName来⾃定义根元素名称,默认false
//是否缩放排列输出,默认false
/
/序列化Date⽇期时以timestamps输出,默认true
//序列化枚举是否以toString()来输出,默认false,即默认以name()来输出
//序列化枚举是否以ordinal()来输出,默认false
//序列化单元素数组时不以数组来输出,默认false
//序列化Map时对key进⾏排序操作,默认false
//序列化char[]时以json数组输出,默认false
//序列化BigDecimal时是输出原始数字还是科学计数,默认false,即以toPlainString()科学计数⽅式来输出
  下⾯写⼀个Person类,对上⾯介绍的序列化属性进⾏测试,并进⾏直观输出: 
1 import com.fasterxml.jackson.annotation.JsonRootName;
2 import org.apachemons.lang3.StringUtils;
3 import java.util.Date;
4
5
6 @JsonRootName("Test")
7 public class Person {
8 //  @JsonInclude(JsonInclude.Include.NON_NULL)
9  private String name;
10
11  private int age;
12
13  private SexEnum sex;
14
15  private Date birthDay;
16
17  public enum SexEnum{
18    MAN("M", "m"),
19    WOMAN("F", "f");
20
21    private String merchantCode;
22    private String nativeCode;
23
24    SexEnum(String merchantCode, String nativeCode) {
25      hantCode = merchantCode;
26      this.nativeCode = nativeCode;
27    }
28
29    public String getMerchantCode() {
30      return merchantCode;
31    }
32
33    public void setMerchantCode(String merchantCode) {
34      hantCode = merchantCode;
35    }
36
37    public String getNativeCode() {
38      return nativeCode;
39    }
40
41    public void setNativeCode(String nativeCode) {
42      this.nativeCode = nativeCode;
43    }
44
45    @Override
46    public String toString() {
47      return getMerchantCode();
48    }
49
50  public Person() {
51  }
52
53  public Person(String name, int age) {
54    this.name = name;
55    this.age = age;
56  }
57
58  public String getName() {
59    return name;
60  }
61
62  public void setName(String name) {
63    this.name = name;
64  }
65
66  public int getAge() {
67    return age;
68  }
69
70  public void setAge(int age) {
71    this.age = age;
72  }
73
74  public SexEnum getSex() {
75    return sex;
76  }
77
78  public void setSex(SexEnum sex) {
79    this.sex = sex;
80  }
81
82  public Date getBirthDay() {
83    return birthDay;
84  }
85
86  public void setBirthDay(Date birthDay) {
87    this.birthDay = birthDay;
88  }
89 }
View Code
  下⾯是测试类:
1 import com.alibaba.fastjson.JSONObject;
2 FirstProject.domain.Person;
3 FirstProject.util.JacksonUtil;
4 import org.joda.time.DateTime;
5 import java.math.BigDecimal;
6 import java.util.ArrayList;
7 import java.util.Date;
8 import java.util.List;
9 import FirstProject.domain.Person.SexEnum;
10 import FirstProject.domain.Person.SexEnum.MAN;
11
12
13 /**
14  * Created by bjxiaojian on 2016/10/26.
15  */
16 public class JacksonTest {
17
18  public static void main(String[] args) {
19
20    Person person = new Person();
21
22    Person person1 = new Person("xiaojian", 1);
23    person1.setSex(MAN);
24    person1.setBirthDay(new Date());
25    List personList = new ArrayList();
26    personList.add(person);
27    personList.add(person1);
28    System.out.de(person));
29    System.out.de(person1));
30    System.out.de(personList));
31
32  }
33 }
34
35
36 ---------------------------------输出结果--------------------------------------------
37 {"Test":{"age":0}}  null的属性不进⾏序列化
38 {"Test":{"age":1,"birthDay":1477661674628,"name":"xiaojian","sex":"M"}}  date类型的输出为时间戳,枚举类的输出默认为MAN或WOMAN,设置后为SexEnum的toString()的返回值
39 {"ArrayList":[{"age":0},{"age":1,"birthDay":1477661674628,"name":"xiaojian","sex":"M"}]}
View Code
  3.2 反序列化属性
1        //当遇到未知属性(没有映射到属性,没有任何setter或者任何可以处理它的handler,是否应该抛出JsonMappingException异常
2        figure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
3        //该特性决定对于json浮点数,是否使⽤BigDecimal来序列化。如果不允许,则使⽤Double序列化。
默认为false
4        figure(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS, false);
5        //该特性决定对于json整形(⾮浮点),是否使⽤BigInteger来序列化。如果不允许,则根据数值⼤⼩来确定是使⽤Integer或者Long
6        figure(DeserializationFeature.USE_BIG_INTEGER_FOR_INTS, false);
7        //该特性决定JSON ARRAY是映射为Object[]还是List<Object>。如果开启,都为Object[],false时,则使⽤List  默认为false
8        figure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, false);
9        //是否使⽤String()的值对json string进⾏反序列化。这个的设置和WRITE_ENUMS_USING_TO_STRING需要⼀致。
10        figure(DeserializationFeature.READ_ENUMS_USING_TO_STRING, true);
View Code
   3.3 Jackson序列化和反序列化注解 
  上⾯的配置是针对所有类的反序列化的设置,下⾯介绍针对某个类的属性和⽅法的反序列化的注解:
  1. @JsonIgnore:作⽤在字段或⽅法上,⽤来完全忽略被注解的字段和⽅法对应的属性。
  2.@JsonProperty:作⽤在字段或⽅法上,⽤来对属性的序列化/反序列化,可以⽤来避免遗漏属性,同时提供对属性名称重命名。
    对属性添加了@JsonProperty注解后,即使该属性为private且没有getter和setter⽅法,也会进⾏序列化。
  3.@JsonIgnoreProperties
    作⽤在类上,⽤来说明有些属性在序列化/反序列化时需要忽略掉,可以将它看做是@JsonIgnore的批量操作,它还有⼀个重要的功能是作⽤在反序列化时解析字段时过滤⼀些未知的属性,否则通常情况下解析到我们定义的类不认识的属性便会抛出异常。
    可以注明是想要忽略的属性列表如@JsonIgnoreProperties({"name","age","title"}),
    也可以注明过滤掉未知的属性如@JsonIgnoreProperties(ignoreUnknown=true)
  4、@JsonUnwrapped作⽤在属性字段或⽅法上,⽤来将⼦JSON对象的属性添加到封闭的JSON对象。⽰例如下:
public void jsonUnwrapped() throws Exception {
TestPOJO testPOJO = new TestPOJO();
testPOJO.setId(111);
TestName testName = new TestName();
testName.setFirstName("张");
testName.setSecondName("三");
testPOJO.setName(testName);
ObjectMapper objectMapper = new ObjectMapper();
String jsonStr = objectMapper.writeValueAsString(testPOJO);
//如果没有@JsonUnwrapped,序列化后将为{"id":111,"name":{"firstName":"张","secondName":"三"}}
//因为在name属性上加了@JsonUnwrapped,所以name的⼦属性firstName和secondName将不会包含在name中。
Assert.assertEquals("{\"id\":111,\"firstName\":\"张\",\"secondName\":\"三\"}",jsonStr);
String jsonStr2 = "{\"id\":111,\"firstName\":\"张\",\"secondName\":\"三\"}";
TestPOJO testPOJO2 = adValue(jsonStr2,TestPOJO.class);
Assert.assertEquals(Id());
Assert.assertEquals("张",Name().getFirstName());
Assert.assertEquals("三",Name().getSecondName());
}
public static class TestPOJO{
private int id;
@JsonUnwrapped
private TestName name;
//getters、setters省略
}
public static class TestName{
private String firstName;
private String secondName;
//getters、setters省略
}
View Code
 5.@JsonSerialize和@JsonDeserialize:作⽤于⽅法和字段上,通过 using(JsonSerializer)和using(Js
onDeserializer)来指定序列化和反序列化的实现。下⾯的例⼦中⾃定义了⽇期的序列化和反序列化⽅式,可以将Date和指定⽇期格式字符串之间相互转换。 
@JsonSerialize(using = MyDateSerializer.class)
@JsonDeserialize(using = MyDateDeserializer.class)
private Date birthday;
  6.@JsonPropertyOrder:作⽤在类上,被⽤来指明当序列化时需要对属性做排序。@jsonPropertyOrder(alphabetic = true)
  7.@JsonView:视图模板,作⽤于⽅法和属性上,⽤来指定哪些属性可以被包含在JSON视图中,在前⾯我们知道已经有@JsonIgnore和
@JsonIgnoreProperties可以排除过滤掉不需要序列化的属性,可是如果⼀个POJO中有h很多个属性,⽽我们可能只需要概要简单信息即序列化时只想输出其中⼏个属性,此时使⽤@JsonIgnore和@JsonIgnoreProperties就显得⾮常繁琐,⽽使⽤@JsonView便会⾮常⽅便,只许在你想要输出的属性(或对应的getter)上添加@JsonView即可。
@Test
public void jsonView() throws Exception {
TestPOJO testPOJO = new TestPOJO();
testPOJO.setA("1");
testPOJO.setB("2");
testPOJO.setC("3");
testPOJO.setD("4");
ObjectMapper objectMapper = new ObjectMapper();
String jsonStr = objectMapper.writerWithView(FilterView.OutputA.class).writeValueAsString(testPOJO);
Assert.assertEquals("{\"a\":\"1\",\"c\":\"3\"}",jsonStr);
String jsonStr2 = objectMapper.writerWithView(FilterView.OutputB.class).writeValueAsString(testPOJO);
Assert.assertEquals("{\"d\":\"4\",\"b\":\"2\"}",jsonStr2);
}
public static class TestPOJO{
@JsonView(FilterView.OutputA.class)
private String a;
@JsonView(FilterView.OutputA.class)
private String c;
@JsonView(FilterView.OutputB.class)
private String d;
@JsonView(FilterView.OutputB.class)
private String b;
//getters、setters忽略
}
private static class FilterView {
static class OutputA {}
static class OutputB {}
}
View Code
  8.@JsonFilter:Json属性过滤器,作⽤于类,作⽤同上⾯的@JsonView,都是过滤掉不想要的属性,输出⾃⼰想要的属性。和@FilterView不同的是@JsonFilter可以动态的过滤属性。eg:
@Test
public void jsonFilter() throws Exception {
TestPOJO testPOJO = new TestPOJO();
testPOJO.setA("1");
testPOJO.setB("2");

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。