1、先搞兩個測試須要使用的類java
2、簡單操做:obj與json互轉json
2.一、對象轉json字符串數組
2.二、json字符串轉對象app
3、拓展需求測試
3.一、對象轉json時,忽略某個字段spa
3.二、對象轉json時,自定義json中的屬性名xml
3.三、對象轉json時,忽略對象中爲null或者""的屬性對象
3.四、json轉對象時,忽略json中未知的屬性blog
3.五、對象轉json時,生成格式化的json字符串字符串
分別是Staff(員工)和Department(部門)
package cn.ganlixin.demo; import lombok.Data; @Data public class Department { private String depName; private String addr; private String superior; }
package cn.ganlixin.demo; import lombok.Data; import java.util.List; import java.util.Map; @Data public class Staff { private int id; private String name; private boolean isAdult; private List<String> languages; private Map<String, Object> scores; private Department department; }
核心代碼段
ObjectMapper mapper = new ObjectMapper(); String jsonStr = mapper.writeValueAsString(Object obj); // Object就是須要序列化(轉換爲json字符串的對象)
示例
/** * 對象 轉爲 json字符串 */ @Test public void test1() throws JsonProcessingException { ObjectMapper mapper = new ObjectMapper(); List<String> languages = new ArrayList<>(); languages.add("Java"); languages.add("PHP"); languages.add("Python"); String languagesJsonStr = mapper.writeValueAsString(languages); System.out.println(languagesJsonStr); // ["Java","PHP","Python"] Map<String, Object> scores = new HashMap<>(); scores.put("math", 59); scores.put("english", 58); String scoresJsonStr = mapper.writeValueAsString(scores); System.out.println(scoresJsonStr); // {"english":58,"math":59} Department department = new Department(); department.setDepName("QA"); department.setAddr("beijing"); department.setSuperior("小強"); String departmentJsonStr = mapper.writeValueAsString(department); System.out.println(departmentJsonStr); // {"depName":"QA","addr":"beijing","superior":"小強"} }
核心代碼
ObjectMapper mapper = new ObjectMapper(); Staff staff = mapper.readValue(jsonStr, Staff.class); // 表示將json字符串的內容轉換爲Staff類的對象
示例:
/** * 將json字符串轉換爲對象 */ @Test public void test2() throws IOException { ObjectMapper mapper = new ObjectMapper(); String languageJsonStr = "[\"Java\",\"PHP\",\"Python\"]"; final List languages = mapper.readValue(languageJsonStr, List.class); System.out.println(languages); // [Java, PHP, Python] String scoresJsonStr = "{\"english\":58,\"math\":59}"; Map<String, Object> scores = mapper.readValue(scoresJsonStr, Map.class); System.out.println(scores); // {english=58, math=59} String departmentJsonStr = "{\"depName\":\"QA\",\"addr\":\"beijing\",\"superior\":\"小強\"}"; final Department department = mapper.readValue(departmentJsonStr, Department.class); System.out.println(department); // Department(depName=QA, addr=beijing, superior=小強) }
有些場景中,某些字段在序列化爲json的時候,應該省略掉,好比一個員工的工資,某個用戶的密碼.....
案例:假設有一個department對象,在轉爲json時,superior(上級)這個字段不能出如今轉換後的json中
方案1:在不須要參與json序列化的字段前增長@JsonIgnore註解便可
@Data public class Department { private String depName; private String addr; @JsonIgnore // 加了@JsonIgnor字段後,superior字段將不參與json序列化 private String superior; }
方案2:在類上面使用@JsonIgnoreProperties({"field1", "field2"})來指定哪些字段不參與json序列化
@Data @JsonIgnoreProperties({"superior"}) // 在@JsonIgnoreProperties註解中指定不參與json序列化的字段便可(接收字符串數組) public class Department { private String depName; private String addr; private String superior; }
測試
/** * 對象轉json時,忽略某個字段 */ @Test public void test3() throws JsonProcessingException { ObjectMapper mapper = new ObjectMapper(); Department department = new Department(); department.setDepName("QA"); department.setAddr("beijing"); department.setSuperior("小強"); final String departmentJsonStr = mapper.writeValueAsString(department); System.out.println(departmentJsonStr); // {"depName":"QA","addr":"beijing"} }
常常會碰到咱們的模型類中定義的屬性名稱,與外部傳入的json字符串中的名稱不相同的狀況,好比Department類中的superior屬性,接收到外部系統傳過來的json字符串中,對應upLevel字段。
在序列化時(obj->json)和反序列化時(json->obj)都須要解決上面superior到upLevel的對應問題,Jackson中提供了一個@JsonProperty註解來解決這個問題
@Data public class Department { private String depName; private String addr; @JsonProperty("upLevel") // 指定序列化與反序列化時,superior屬性對應的名稱:序列化時,superior對應到upLevel屬性,反序列化時,upLevel對應到superior屬性 private String superior; }
示例:
/** * 對象與json互轉時,自定義對應名稱 */ @Test public void test4() throws IOException { ObjectMapper mapper = new ObjectMapper(); Department department1 = new Department(); department1.setDepName("QA"); department1.setAddr("beijing"); department1.setSuperior("小強"); // 對象序列化爲json字符串,注意superior屬性轉json時會變爲upLevel String departmentJsonStr = mapper.writeValueAsString(department1); System.out.println(departmentJsonStr); // {"depName":"QA","addr":"beijing","upLevel":"小強"} // 利用上面序列化的字符串,反序列爲對象,upLevel字段會對應到Department對象的superior屬性 Department department2 = mapper.readValue(departmentJsonStr, Department.class); System.out.println(department2); // Department(depName=QA, addr=beijing, superior=小強) }
這個需求是這樣的,對象中,有的屬性值是null或者空字符串,此時,咱們不但願轉換後的json字符串中包含該屬性值爲null或者空字符串的字段。
好比Department類中的superior屬性,對於老闆來講,沒有上級,則superior的值爲null或者"",此時但願序列化後的json字符串省略superior字段(這與前面的省略某個字段不一樣)。
Jackson在將對象序列化爲json字符串時,默認是在類級別添加了@JsonInclude(JsonInclude.Include.ALWAYS)註解,表示默認將對象的全部字段都序列化(即便屬性值爲null或者空字符串)。
要實現忽略對象中屬性值爲null或者""的屬性值,能夠這樣作:
方案1:
@JsonInclude(JsonInclude.Include.NON_NULL) 能夠加在指定的字段前(局部),也能夠加在類級別上(全局),當屬性值不爲null的時候纔會參加序列化
@JsonInclude(JsonInclude.Include.NON_EMPTY) 能夠加在指定的字段前(局部),也能夠加在類級別上(全局),當設置屬性值爲null或者""的時候,該屬性不會參加序列化;
注意,對於上面兩個註解,若是類中聲明該屬性有默認值,即便沒有爲該屬性設置屬性值,那麼該屬性仍舊會參加序列化。
@Data public class Department { private String depName; private String addr; @JsonInclude(JsonInclude.Include.NON_NULL) // 加在指定的字段前,當屬性值不爲null的時候纔會參加序列化 private String superior; }
方案2:
方案1使用於要序列化的類數量很少的狀況,若是要進行序列化的類很是多,而且都須要忽略屬性值爲null或者""的屬性,那麼對每個類進行設置@JsonInclude(xxxx)也是很麻煩的,這個時候,咱們能夠從ObjectMapper上進行配置,使用配置後的ObjectMapper,那麼在序列化的時候,自動回忽略值爲null或者""的屬性值。
/** * 全局設置對象轉json時忽略值爲null或者""的屬性 */ @Test public void test7() throws JsonProcessingException { ObjectMapper mapper = new ObjectMapper(); // 設置忽略null和""的屬性值,這裏的Include與方案1的一致 mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY); Department department1 = new Department(); department1.setDepName("QA"); department1.setAddr(""); department1.setSuperior(null); String depJsonStr = mapper.writeValueAsString(department1); System.out.println(depJsonStr); // {"depName":"QA"} }
這個場景是指,json中有一個字段,在類中找很少與之對應的屬性,此時若是強請轉換爲指定類,那麼就會報錯
@Test public void test8() throws IOException { // 注意,json串中多了age字段,而Department類中並沒有該屬性(且無屬性與之對應,好比使用@JsonProperty進行設置) String json = "{\"depName\":\"QA\",\"addr\":\"beijing\", \"age\":99}"; ObjectMapper mapper = new ObjectMapper(); final Department department = mapper.readValue(json, Department.class); System.out.println(department); }
上面的運行時會報錯:com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "age" (class cn.ganlixin.demo.Department), not marked as ignorable....
這個狀況,能夠經過設置mapper來解決問題
/** * 忽略json中未知的字段名 */ @Test public void test9() throws IOException { String json = "{\"depName\":\"QA\",\"addr\":\"beijing\", \"age\":99}"; ObjectMapper mapper = new ObjectMapper(); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // 表示遇到未知屬性時,不會報錯 final Department department = mapper.readValue(json, Department.class); System.out.println(department); // Department(depName=QA, addr=beijing, superior=null) }
在writeValueAsString(Object obj)以前,mapper先調用writerWithDefaultPrettyPrinter()方法便可
@Test public void test6() throws JsonProcessingException { ObjectMapper mapper = new ObjectMapper(); Department department1 = new Department(); department1.setDepName("QA"); department1.setAddr("beijing"); department1.setSuperior("小強"); final String depJsonStr = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(department1); System.out.println(depJsonStr); /* { "depName" : "QA", "addr" : "beijing", "superior" : "小強" } */ }