這篇文章主要講解了“Jackson的組成部分有哪些”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Jackson的組成部分有哪些”吧!
成都創(chuàng)新互聯(lián),為您提供成都網站建設、成都網站制作、網站營銷推廣、網站開發(fā)設計,對服務混凝土攪拌機等多個行業(yè)擁有豐富的網站建設及推廣經驗。成都創(chuàng)新互聯(lián)網站建設公司成立于2013年,提供專業(yè)網站制作報價服務,我們深知市場的競爭激烈,認真對待每位客戶,為客戶提供賞心悅目的作品。 與客戶共同發(fā)展進步,是我們永遠的責任!
Jackson是比較主流的基于Java的JSON類庫,可用于Json和XML與JavaBean之間的序列化和反序列化。
沒看錯,Jackson也可以處理JavaBean與XML之間的轉換,基于jackson-dataformat-xml組件,而且比較JDK自帶XML實現(xiàn)更加高效和安全。而我們使用比較多的是處理JSON與JavaBean之間的功能。
Jackson主流到什么程度?單從Maven倉庫中的統(tǒng)計來看,Jackson的使用量排位第一。而Spring Boot支持的三個JSON庫(Gson、Jackson、JSON-B)中,Jackson是首選默認庫。
Jackson也有以下特點:依賴少,簡單易用,解析大Json速度快、內存占用比較低、擁有靈活的API、方便擴展與定制。
Jackson的核心模塊由三部分組成(從Jackson 2.x開始):jackson-core、jackson-annotations、jackson-databind。
jackson-core:核心包,定義了低級流(Streaming)API,提供基于"流模式"解析。Jackson內部實現(xiàn)正是通過高性能的流模式API的JsonGenerator和JsonParser來生成和解析json。
jackson-annotations,注解(Annotations)包,提供標準的Jackson注解功能;
jackson-databind:數據綁定(Databind)包,實現(xiàn)了數據綁定(和對象序列化)支持,它依賴于Streaming和Annotations包。提供基于“對象綁定”解析的API(ObjectMapper)和"樹模型"解析的API(JsonNode);基于"對象綁定"解析的API和"樹模型"解析的API依賴基于“流模式”解析的API。
下面看一下不同環(huán)境下相關組件的依賴引入情況。
在SpringBoot當中,spring-boot-starter-web間接引入了Jackson組件,也就是如果你使用了SpringBoot框架,那么你的項目中已經有了Jackson依賴。下面的依賴省略了version和scope項。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
web starter中依賴了json starter:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-json</artifactId> </dependency>
json starter最終引入了Jackson:
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> <dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jdk8</artifactId> </dependency> <dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jsr310</artifactId> </dependency> <dependency> <groupId>com.fasterxml.jackson.module</groupId> <artifactId>jackson-module-parameter-names</artifactId> </dependency>
上面已經提到過,jackson-databind依賴于Streaming和Annotations包,因此,引入jackson-databind相當于引入了jackson-core和jackson-annotations。
通常情況下,我們單獨使用時,根據需要通過Maven引入jackson-databind、jackson-core和jackson-annotations即可。
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency>
對于SpringBoot項目,基本上不用再額外添加依賴。
Jackson提供了三種JSON的處理方式,分別是:數據綁定、JSON樹模型、流式API。其中前兩項功能都是基于ObjectMapper來實現(xiàn)的,而流式API功能則需要基于更底層的JsonGenerator和JsonParser來實現(xiàn)。
通常情況下我們使用ObjectMapper類就足夠了,它擁有以下功能:
從字符串、流或文件中解析JSON,并創(chuàng)建表示已解析的JSON的Java對象(反序列化)。
將Java對象構建成JSON字符串(序列化)。
將JSON解析為自定義類的對象,也可以解析JSON樹模型的對象;
ObjectMapper基于JsonParser和JsonGenerator來實現(xiàn)JSON實際的讀/寫。這一點看一下ObjectMapper的構造方法即可明白。
Jackson的常見使用,就不逐一講解了,通過一些列的實例給大家展示一下,每個實例當中都會通過注釋進行說明。
下面的示例是我們經常會用到的用法演示,主要涉及到JavaBean和Json字符串之間的轉換。
Jackson在將json轉換為JavaBean屬性時,默認是通過Json字段的名稱與Java對象中的getter和setter方法進行匹配進行綁定。
Jackson取getter和setter方法名稱中去除“get”和“set”部分,并將首字母小寫。例如Json中的name,與JavaBean中的getName()和setName()進行匹配。
但并不是所有的屬性都可以被序列化和反序列化,基本上遵循一下規(guī)則:
public修飾的屬性可序列化和反序列化。
屬性提供public的getter/setter方法,該屬性可序列化和反序列化。
屬性只有public的setter方法,而無public的getter方法,該屬性只能用于反序列化。
@Slf4j public class JacksonTest { /** * JavaBean轉JSON字符串 */ @Test public void testJavaBeanToJson() { WeChat weChat = new WeChat(); weChat.setId("zhuan2quan"); weChat.setName("程序新視界"); weChat.setInterest(new String[]{"Java", "Spring Boot", "JVM"}); ObjectMapper mapper = new ObjectMapper(); try { String result = mapper.writeValueAsString(weChat); System.out.println(result); } catch (JsonProcessingException e) { log.error("轉換異常", e); } } /** * JSON字符串轉JavaBean */ @Test public void testJsonToJavaBean() { String json = "{\"id\":\"zhuan2quan\",\"name\":\"程序新視界\",\"interest\":[\"Java\",\"Spring Boot\",\"JVM\"]}"; ObjectMapper mapper = new ObjectMapper(); try { WeChat weChat = mapper.readValue(json, WeChat.class); System.out.println(weChat); } catch (JsonProcessingException e) { log.error("解析異常", e); } } /** * JSON字符串轉Map集合 */ @Test public void testJsonToMap() { String json = "{\"id\":\"zhuan2quan\",\"name\":\"程序新視界\",\"interest\":[\"Java\",\"Spring Boot\",\"JVM\"]}"; ObjectMapper mapper = new ObjectMapper(); try { // 對泛型的反序列化,使用TypeReference可以明確的指定反序列化的類型。 Map<String, Object> map = mapper.readValue(json, new TypeReference<Map<String, Object>>() { }); System.out.println(map); } catch (JsonProcessingException e) { log.error("解析異常", e); } } /** * JavaBean轉文件 */ @Test public void testJavaBeanToFile() { WeChat weChat = new WeChat(); weChat.setId("zhuan2quan"); weChat.setName("程序新視界"); weChat.setInterest(new String[]{"Java", "Spring Boot", "JVM"}); ObjectMapper mapper = new ObjectMapper(); try { //寫到文件 mapper.writeValue(new File("/json.txt"), weChat); //從文件中讀取 WeChat weChat1 = mapper.readValue(new File("/json.txt"), WeChat.class); System.out.println(weChat1); } catch (IOException e) { log.error("轉換異常", e); } } /** * JavaBean轉字節(jié)流 */ @Test public void testJavaBeanToBytes() { WeChat weChat = new WeChat(); weChat.setId("zhuan2quan"); weChat.setName("程序新視界"); weChat.setInterest(new String[]{"Java", "Spring Boot", "JVM"}); ObjectMapper mapper = new ObjectMapper(); try { // 寫為字節(jié)流 byte[] bytes = mapper.writeValueAsBytes(weChat); // 從字節(jié)流讀取 WeChat weChat1 = mapper.readValue(bytes, WeChat.class); System.out.println(weChat1); } catch (IOException e) { log.error("轉換異常", e); } } }
上述代碼用到了lombok注解和單元測試注解,根據需要可進行替換。
如果Json字符串比較大,則可使用JSON樹模型來靈活的獲取所需的字段內容。在Jackson中提供了get、path、has等方法來獲取或判斷。
下面直接看兩個示例:
@Slf4j public class JacksonNodeTest { /** * JavaBean轉JSON字符串 */ @Test public void testJsonNode() { // 構建JSON樹 ObjectMapper mapper = new ObjectMapper(); ObjectNode root = mapper.createObjectNode(); root.put("id", "zhuan2quan"); root.put("name", "程序新視界"); ArrayNode interest = root.putArray("interest"); interest.add("Java"); interest.add("Spring Boot"); interest.add("JVM"); // JSON樹轉JSON字符串 String json = null; try { json = mapper.writeValueAsString(root); } catch (JsonProcessingException e) { log.error("Json Node轉換異常", e); } System.out.println(json); } /** * 解析JSON字符串為JSON樹模型 */ @Test public void testJsonToJsonNode() { String json = "{\"id\":\"zhuan2quan\",\"name\":\"程序新視界\",\"interest\":[\"Java\",\"Spring Boot\",\"JVM\"]}"; ObjectMapper mapper = new ObjectMapper(); try { // 將JSON字符串轉為JSON樹 JsonNode jsonNode = mapper.readTree(json); String name = jsonNode.path("name").asText(); System.out.println(name); JsonNode interestNode = jsonNode.get("interest"); if (interestNode.isArray()){ for (JsonNode node : interestNode){ System.out.println(node.asText()); } } } catch (JsonProcessingException e) { log.error("Json Node轉換異常", e); } } }
其中get方法和path功能相似,區(qū)別在于如果要讀取的key在Json串中不存在時,get方法會null,而path會返回MissingNode實例對象,在鏈路方法情況下保證不會拋出異常。
除了上述兩種形式,還可以基于底層的流式API來進行操作,主要通過JsonGenerator和JsonParser兩個API,但操作起來比較復雜,就不再這里演示了。
在使用ObjectMapper時,會存在一些字段在某些情況下不需要進行序列化或反序列化,同時還可能需要指定格式化的一些信息等。此時,可以通過ObjectMapper進行配置。
//反序列化時忽略json中存在但Java對象不存在的屬性 mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); //序列化時日期格式默認為yyyy-MM-dd'T'HH:mm:ss.SSSZ mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); //序列化時自定義時間日期格式 mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); //序列化時忽略值為null的屬性 mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); //序列化時忽略值為默認值的屬性 mapper.setDefaultPropertyInclusion(JsonInclude.Include.NON_DEFAULT);
針對于配置項,在2.2版本中新增了一個ObjectMapper的實現(xiàn)類JsonMapper,功能與ObjectMapper一致。不過新增了一個builder方法。可以直接通過JsonMapper.builder().configure()方法來進行配置,最后獲得一個JsonMapper對象。JsonMapper的其他方法基本都集成自ObjectMapper。
上面通過統(tǒng)一配置可對全局格式的序列化和反序列化進行配置,但某些個別的場景下,需要針對具體的字段進行配置,這就需要用注解。比如當Json字符串中的字段與Java對象中的屬性不一致時,就需要通過注解來建立它們直接的關系。
@JsonProperty,作用JavaBean字段上,指定一個字段用于JSON映射,默認情況下映射的JSON字段與注解的字段名稱相同。可通過value屬性指定映射的JSON的字段名稱。
@JsonIgnore可用于字段、getter/setter、構造函數參數上,指定字段不參與序列化和反序列化。
@JsonIgnoreProperties作用于類上,序列化時@JsonIgnoreProperties({“prop1”, “prop2”})會忽略pro1和pro2兩個屬性。反序列化時@JsonIgnoreProperties(ignoreUnknown=true)會忽略類中不存在的字段。
@JsonFormat作用于字段上,通常用來進行格式化操作。
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date date;
如果JavaBean中的時間字段使用的是JDK8新增的時間日期(LocalDate/LocalTime/LocalDateTime)類型的話,需要添加jackson-datatype-jsr310依賴。在講依賴部分時,SpringBoot默認引入的依賴中就有這個。
當然,還有一些其他的注解,比如@JsonPropertyOrder、@JsonRootName、@JsonAnySetter、@JsonAnyGetter、@JsonNaming等,當使用時參考對應的文檔和示例看一下就可以,這里就不再一一列出了。
如果上面的注解和統(tǒng)一配置還無法滿足需求,可自定義解析器,示例如下:
public class MyFastjsonDeserialize extends JsonDeserializer<Point> { @Override public Point deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException { JsonNode node = jsonParser.getCodec().readTree(jsonParser); Iterator<JsonNode> iterator = node.get("coordinates").elements(); List<Double> list = new ArrayList<>(); while (iterator.hasNext()) { list.add(iterator.next().asDouble()); } return new Point(list.get(0), list.get(1)); } }
定義完成之后,注冊到Mapper中:
ObjectMapper objectMapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); module.addDeserializer(Point.class, new MyFastjsonDeserialize()); objectMapper.registerModule(module);
Jackson也可以通過jackson-dataformat-xml包提供了處理XML的功能。在處理XML時建議使用woodstox-core包,它是一個XML的實現(xiàn),比JDK自帶XML實現(xiàn)更加高效,也更加安全。
<dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> </dependency>
如果使用Java 9及以上版本,可能會出現(xiàn)java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException異常,這是因為Java 9實現(xiàn)了JDK的模塊化,將原本和JDK打包在一起的JAXB實現(xiàn)分隔出來。所以需要手動添加JAXB的實現(xiàn)。
<dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> </dependency>
下面是代碼示例,基本上和JSON的API非常相似,XmlMapper實際上就是ObjectMapper的子類。
@Test public void testXml(){ WeChat weChat = new WeChat(); weChat.setId("zhuan2quan"); weChat.setName("程序新視界"); weChat.setInterest(new String[]{"Java", "Spring Boot", "JVM"}); XmlMapper xmlMapper = new XmlMapper(); try { String xml = xmlMapper.writeValueAsString(weChat); System.out.println(xml); } catch (JsonProcessingException e) { e.printStackTrace(); } }
執(zhí)行之后,輸出結果:
<WeChat> <id>zhuan2quan</id> <name>程序新視界</name> <interest> <interest>Java</interest> <interest>Spring Boot</interest> <interest>JVM</interest> </interest> </WeChat>
在最開始的時候,我們已經看到Spring Boot默認引入了Jackson的依賴,而且也用我們做什么額外的操作,其實已經在使用Jackson進行Json格式的數據與MVC中參數進行綁定操作了。
如果Spring Boot默認的配置并不適合項目需求,也可以通過內置的配置進行配置,以application.yml配置為例,可通過指定以下屬性進行相應選項的配置:
#指定日期格式,比如yyyy-MM-dd HH:mm:ss,或者具體的格式化類的全限定名 spring.jackson.date-format #是否開啟Jackson的反序列化 spring.jackson.deserialization #是否開啟json的generators. spring.jackson.generator #指定Joda date/time的格式,比如yyyy-MM-ddHH:mm:ss). 如果沒有配置的話,dateformat會作為backup spring.jackson.joda-date-time-format #指定json使用的Locale. spring.jackson.locale #是否開啟Jackson通用的特性. spring.jackson.mapper #是否開啟jackson的parser特性. spring.jackson.parser #指定PropertyNamingStrategy(CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES)或者指定PropertyNamingStrategy子類的全限定類名. spring.jackson.property-naming-strategy #是否開啟jackson的序列化. spring.jackson.serialization #指定序列化時屬性的inclusion方式,具體查看JsonInclude.Include枚舉. spring.jackson.serialization-inclusion #指定日期格式化時區(qū),比如America/Los_Angeles或者GMT+10. spring.jackson.time-zone
Spring Boot自動配置非常方便,但某些時候需要我們手動配置Bean來替代自動配置的Bean。可通過如下形式進行配置:
@Configuration public class JacksonConfig { @Bean @Qualifier("json") public ObjectMapper jsonMapper(Jackson2ObjectMapperBuilder builder) { ObjectMapper mapper = builder.createXmlMapper(false) .build(); mapper.enable(SerializationFeature.INDENT_OUTPUT); mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); return mapper; } }
配置完成,可在使用的地方直接注入即可:
@Resource private ObjectMapper jsonMapper;
對于上面的注入,可能會有朋友問了,是否有線程安全的問題?這個不用擔心ObjectMapper是線程安全的。
感謝各位的閱讀,以上就是“Jackson的組成部分有哪些”的內容了,經過本文的學習后,相信大家對Jackson的組成部分有哪些這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關知識點的文章,歡迎關注!
網站名稱:Jackson的組成部分有哪些
轉載來源:http://www.chinadenli.net/article18/ggijgp.html
成都網站建設公司_創(chuàng)新互聯(lián),為您提供Google、網站建設、品牌網站建設、做網站、企業(yè)建站、手機網站建設
聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)