日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Jackson用法详解

發(fā)布時(shí)間:2025/3/12 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Jackson用法详解 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Spring MVC 默認(rèn)采用Jackson解析Json,盡管還有一些其它同樣優(yōu)秀的json解析工具,例如Fast Json、GSON,但是出于最小依賴的考慮,也許Json解析第一選擇就應(yīng)該是Jackson。

一、簡(jiǎn)介

Jackson 是當(dāng)前用的比較廣泛的,用來(lái)序列化和反序列化 json 的 Java 的開(kāi)源框架。Jackson 社區(qū)相對(duì)比較活躍,更新速度也比較快, 從 Github 中的統(tǒng)計(jì)來(lái)看,Jackson 是最流行的 json 解析器之一 。 Spring MVC 的默認(rèn) json 解析器便是 Jackson。 Jackson 優(yōu)點(diǎn)很多。 Jackson 所依賴的 jar 包較少 ,簡(jiǎn)單易用。與其他 Java 的 json 的框架 Gson 等相比, Jackson 解析大的 json 文件速度比較快;Jackson 運(yùn)行時(shí)占用內(nèi)存比較低,性能比較好;Jackson 有靈活的 API,可以很容易進(jìn)行擴(kuò)展和定制。

Jackson 的 1.x 版本的包名是 org.codehaus.jackson ,當(dāng)升級(jí)到 2.x 版本時(shí),包名變?yōu)?com.fasterxml.jackson。

Jackson 的核心模塊由三部分組成。

  • jackson-core,核心包,提供基于"流模式"解析的相關(guān) API,它包括 JsonPaser 和 JsonGenerator。 Jackson 內(nèi)部實(shí)現(xiàn)正是通過(guò)高性能的流模式 API 的 JsonGenerator 和 JsonParser 來(lái)生成和解析 json。
  • jackson-annotations,注解包,提供標(biāo)準(zhǔn)注解功能;
  • jackson-databind ,數(shù)據(jù)綁定包, 提供基于"對(duì)象綁定" 解析的相關(guān) API ( ObjectMapper ) 和"樹(shù)模型" 解析的相關(guān) API (JsonNode);基于"對(duì)象綁定" 解析的 API 和"樹(shù)模型"解析的 API 依賴基于"流模式"解析的 API。

源碼地址:FasterXML/jackson

二、依賴

使用Maven構(gòu)建項(xiàng)目,需要添加依賴:

<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.9.6</version> </dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-annotations</artifactId><version>2.9.6</version> </dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.6</version> </dependency>

當(dāng)然了,jackson-databind 依賴 jackson-core 和 jackson-annotations,所以可以只顯示地添加jackson-databind依賴,jackson-core 和 jackson-annotations 也隨之添加到 Java 項(xiàng)目工程中。

<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.6</version> </dependency>

下面是Jackson的用法。

三、 ObjectMapper

Jackson 最常用的 API 就是基于"對(duì)象綁定" 的 ObjectMapper:

  • ObjectMapper可以從字符串,流或文件中解析JSON,并創(chuàng)建表示已解析的JSON的Java對(duì)象。 將JSON解析為Java對(duì)象也稱為從JSON反序列化Java對(duì)象。
  • ObjectMapper也可以從Java對(duì)象創(chuàng)建JSON。 從Java對(duì)象生成JSON也稱為將Java對(duì)象序列化為JSON。
  • Object映射器可以將JSON解析為自定義的類的對(duì)象,也可以解析置JSON樹(shù)模型的對(duì)象。

之所以稱為ObjectMapper是因?yàn)樗鼘SON映射到Java對(duì)象(反序列化),或者將Java對(duì)象映射到JSON(序列化)。

一)、從JSON中獲取Java對(duì)象

1、簡(jiǎn)單示例

一個(gè)簡(jiǎn)單的例子:

Car類:

public class Car {private String brand = null;private int doors = 0;public String getBrand() { return this.brand; }public void setBrand(String brand){ this.brand = brand;}public int getDoors() { return this.doors; }public void setDoors (int doors) { this.doors = doors; } }

將Json轉(zhuǎn)換為Car類對(duì)象:

ObjectMapper objectMapper = new ObjectMapper();String carJson ="{ \"brand\" : \"Mercedes\", \"doors\" : 5 }";try {Car car = objectMapper.readValue(carJson, Car.class);System.out.println("car brand = " + car.getBrand());System.out.println("car doors = " + car.getDoors());} catch (IOException e) {e.printStackTrace();}

2、 ObjectMapper如何匹配JSON對(duì)象的字段和Java對(duì)象的屬性

默認(rèn)情況下,Jackson通過(guò)將JSON字段的名稱與Java對(duì)象中的getter和setter方法進(jìn)行匹配,將JSON對(duì)象的字段映射到Java對(duì)象中的屬性。 Jackson刪除了getter和setter方法名稱的“ get”和“ set”部分,并將其余名稱的第一個(gè)字符轉(zhuǎn)換為小寫。

例如,名為brand的JSON字段與名為getBrand()和setBrand()的Java getter和setter方法匹配。 名為engineNumber的JSON字段將與名為getEngineNumber()和setEngineNumber()的getter和setter匹配。

如果需要以其他方式將JSON對(duì)象字段與Java對(duì)象字段匹配,則需要使用自定義序列化器和反序列化器,或者使用一些Jackson注解。

3、JSON字符串–>Java對(duì)象

從JSON字符串讀取Java對(duì)象非常容易。 上面已經(jīng)有了一個(gè)示例——JSON字符串作為第一個(gè)參數(shù)傳遞給ObjectMapper的readValue()方法。 這是另一個(gè)簡(jiǎn)單的示例:

ObjectMapper objectMapper = new ObjectMapper();String carJson ="{ \"brand\" : \"Mercedes\", \"doors\" : 5 }";Car car = objectMapper.readValue(carJson, Car.class);

3、JSON 字符輸入流–>Java對(duì)象

還可以從通過(guò)Reader實(shí)例加載的JSON中讀取對(duì)象。示例如下:

ObjectMapper objectMapper = new ObjectMapper();String carJson = "{ \"brand\" : \"Mercedes\", \"doors\" : 4 }";Reader reader = new StringReader(carJson);Car car = objectMapper.readValue(reader, Car.class);

4、JSON文件–>Java對(duì)象

從文件讀取JSON當(dāng)然可以通過(guò)FileReader(而不是StringReader)來(lái)完成,也可以通過(guò)File對(duì)象來(lái)完成。 這是從文件讀取JSON的示例:

ObjectMapper objectMapper = new ObjectMapper();File file = new File("data/car.json");Car car = objectMapper.readValue(file, Car.class);

5、JSON via URL—>Java對(duì)象

可以通過(guò)URL(java.net.URL)從JSON讀取對(duì)象,如下所示:

ObjectMapper objectMapper = new ObjectMapper();URL url = new URL("file:data/car.json");Car car = objectMapper.readValue(url, Car.class);

示例使用文件URL,也可以使用HTTP URL(類似于http://jenkov.com/some-data.json)。

6、JSON字節(jié)輸入流–>Java對(duì)象

也可以使用ObjectMapper通過(guò)InputStream從JSON讀取對(duì)象。 這是一個(gè)從InputStream讀取JSON的示例:

ObjectMapper objectMapper = new ObjectMapper();InputStream input = new FileInputStream("data/car.json");Car car = objectMapper.readValue(input, Car.class);

7、JSON二進(jìn)制數(shù)組–>Java對(duì)象

Jackson還支持從JSON字節(jié)數(shù)組讀取對(duì)象。 這是從JSON字節(jié)數(shù)組讀取對(duì)象的示例:

ObjectMapper objectMapper = new ObjectMapper();String carJson ="{ \"brand\" : \"Mercedes\", \"doors\" : 5 }";byte[] bytes = carJson.getBytes("UTF-8");Car car = objectMapper.readValue(bytes, Car.class);

8、JSON數(shù)組字符串–>Java對(duì)象數(shù)組

Jackson ObjectMapper也可以從JSON數(shù)組字符串讀取對(duì)象數(shù)組。 這是從JSON數(shù)組字符串讀取對(duì)象數(shù)組的示例:

String jsonArray = "[{\"brand\":\"ford\"}, {\"brand\":\"Fiat\"}]";ObjectMapper objectMapper = new ObjectMapper();Car[] cars2 = objectMapper.readValue(jsonArray, Car[].class);

需要將Car數(shù)組類作為第二個(gè)參數(shù)傳遞給readValue()方法。

讀取對(duì)象數(shù)組還可以與字符串以外的其他JSON源一起使用。 例如,文件,URL,InputStream,Reader等。

9、JSON數(shù)組字符串–>List

Jackson ObjectMapper還可以從JSON數(shù)組字符串讀取對(duì)象的Java List。 這是從JSON數(shù)組字符串讀取對(duì)象列表的示例:

String jsonArray = "[{\"brand\":\"ford\"}, {\"brand\":\"Fiat\"}]";ObjectMapper objectMapper = new ObjectMapper();List<Car> cars1 = objectMapper.readValue(jsonArray, new TypeReference<List<Car>>(){});

10、JSON字符串–>Map

Jackson ObjectMapper還可以從JSON字符串讀取Java Map。 如果事先不知道將要解析的確切JSON結(jié)構(gòu),這種方法是很有用的。 通常,會(huì)將JSON對(duì)象讀入Java Map。 JSON對(duì)象中的每個(gè)字段都將成為Java Map中的鍵,值對(duì)。

這是一個(gè)使用Jackson ObjectMapper從JSON字符串讀取Java Map的示例:

String jsonObject = "{\"brand\":\"ford\", \"doors\":5}";ObjectMapper objectMapper = new ObjectMapper(); Map<String, Object> jsonMap = objectMapper.readValue(jsonObject,new TypeReference<Map<String,Object>>(){});

11、忽略未知的JSON字段

有時(shí)候,與要從JSON讀取的Java對(duì)象相比,JSON中的字段更多。 默認(rèn)情況下,Jackson在這種情況下會(huì)拋出異常,報(bào)不知道XYZ字段異常,因?yàn)樵贘ava對(duì)象中找不到該字段。

但是,有時(shí)應(yīng)該允許JSON中的字段多于相應(yīng)的Java對(duì)象中的字段。 例如,要從REST服務(wù)解析JSON,而該REST服務(wù)包含的數(shù)據(jù)遠(yuǎn)遠(yuǎn)超出所需的。 在這種情況下,可以使用Jackson配置忽略這些額外的字段。 以下是配置Jackson ObjectMapper忽略未知字段的示例:

objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

12、不允許基本類型為null

如果JSON字符串包含其值設(shè)置為null的字段(對(duì)于在相應(yīng)的Java對(duì)象中是基本數(shù)據(jù)類型(int,long,float,double等)的字段),Jackson ObjectMapper默認(rèn)會(huì)處理基本數(shù)據(jù)類型為null的情況,我們可以可以將Jackson ObjectMapper默認(rèn)配置為失效,這樣基本數(shù)據(jù)為null就會(huì)轉(zhuǎn)換失敗。 例如以下Car類:

public class Car {private String brand = null;private int doors = 0;public String getBrand() { return this.brand; }public void setBrand(String brand){ this.brand = brand;}public int getDoors(){ return this.doors; }public void setDoors (int doors) { this.doors = doors; } }

doors字段是一個(gè)int類型,它是Java中的基本數(shù)據(jù)類型。

現(xiàn)在,假設(shè)有一個(gè)與Car對(duì)象相對(duì)應(yīng)的JSON字符串,如下所示:

{ "brand":"Toyota", "doors":null }

請(qǐng)注意,doors字段值為null。 Java中的基本數(shù)據(jù)類型不能為null值。 默認(rèn)情況下,Jackson ObjectMapper會(huì)忽略原始字段的空值。 但是,可以將Jackson ObjectMapper配置設(shè)置為失敗。

ObjectMapper objectMapper = new ObjectMapper();objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, true);

在FAIL_ON_NULL_FOR_PRIMITIVES配置值設(shè)置為true的情況下,嘗試將空J(rèn)SON字段解析為基本類型Java字段時(shí)會(huì)遇到異常。 這是一個(gè)Java Jackson ObjectMapper示例,該示例將失敗,因?yàn)镴SON字段包含原始Java字段的空值:

ObjectMapper objectMapper = new ObjectMapper();objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, true);String carJson = "{ \"brand\":\"Toyota\", \"doors\":null }";Car car = objectMapper.readValue(carJson, Car.class);

結(jié)果:

13、自定義反序列化

有時(shí),可能希望以不同于Jackson ObjectMapper缺省方式的方式將JSON字符串讀入Java對(duì)象。 可以將自定義反序列化器添加到ObjectMapper,可以按需要執(zhí)行反序列化。

這是在Jackson的ObjectMapper中注冊(cè)和使用自定義反序列化器的方式:

String json = "{ \"brand\" : \"Ford\", \"doors\" : 6 }";SimpleModule module =new SimpleModule("CarDeserializer", new Version(3, 1, 8, null, null, null));module.addDeserializer(Car.class, new CarDeserializer(Car.class));ObjectMapper mapper = new ObjectMapper();mapper.registerModule(module);Car car = mapper.readValue(json, Car.class);

自定義反序列化器CarDeserializer類:

public class CarDeserializer extends StdDeserializer<Car> {public CarDeserializer(Class<?> vc) {super(vc);}@Overridepublic Car deserialize(JsonParser parser, DeserializationContext deserializer) throws IOException {Car car = new Car();while(!parser.isClosed()){JsonToken jsonToken = parser.nextToken();if(JsonToken.FIELD_NAME.equals(jsonToken)){String fieldName = parser.getCurrentName();System.out.println(fieldName);jsonToken = parser.nextToken();if("brand".equals(fieldName)){car.setBrand(parser.getValueAsString());} else if ("doors".equals(fieldName)){car.setDoors(parser.getValueAsInt());}}}return car;} }

二)、將對(duì)象寫入JSON

1、Java對(duì)象–>JSON

Jackson ObjectMapper也可以用于從對(duì)象生成JSON。 可以使用以下方法之一進(jìn)行操作:

  • writeValue()
  • writeValueAsString()
  • writeValueAsBytes()

這是一個(gè)從Car對(duì)象生成JSON的示例,和上面的實(shí)例相反:

ObjectMapper objectMapper = new ObjectMapper();Car car = new Car();car.setBrand("BMW");car.setDoors(4);objectMapper.writeValue(new FileOutputStream("data/output-2.json"), car);

此示例首先創(chuàng)建一個(gè)ObjectMapper,然后創(chuàng)建一個(gè)Car實(shí)例,最后調(diào)用ObjectMapper的writeValue()方法,該方法將Car對(duì)象轉(zhuǎn)換為JSON并將其寫入給定的FileOutputStream。

ObjectMapper的writeValueAsString()和writeValueAsBytes()都從一個(gè)對(duì)象生成JSON,并將生成的JSON作為String或字節(jié)數(shù)組返回。 示例如下:

ObjectMapper objectMapper = new ObjectMapper();Car car = new Car();car.setBrand("寶馬");car.setDoors(4);String json = objectMapper.writeValueAsString(car);System.out.println(json);

運(yùn)行結(jié)果:

2、自定義序列化

有時(shí),想要將Java對(duì)象序列化為JSON的方式與使用Jackson的默認(rèn)方式不同。 例如,可能想要在JSON中使用與Java對(duì)象中不同的字段名稱,或者希望完全省略某些字段。

Jackson可以在ObjectMapper上設(shè)置自定義序列化器。 該序列化器已為某個(gè)類注冊(cè),然后在每次要求ObjectMapper序列化Car對(duì)象時(shí)將調(diào)用該序列化器。

這是為Car類注冊(cè)自定義序列化器的示例:

CarSerializer carSerializer = new CarSerializer(Car.class);ObjectMapper objectMapper = new ObjectMapper();SimpleModule module =new SimpleModule("CarSerializer", new Version(2, 1, 3, null, null, null));module.addSerializer(Car.class, carSerializer);objectMapper.registerModule(module);Car car = new Car();car.setBrand("Mercedes");car.setDoors(5);String carJson = objectMapper.writeValueAsString(car);

自定義序列化器CarSerializer類:

public class CarSerializer extends StdSerializer<Car> {protected CarSerializer(Class<Car> t) {super(t);}public void serialize(Car car, JsonGenerator jsonGenerator,SerializerProvider serializerProvider)throws IOException {jsonGenerator.writeStartObject();jsonGenerator.writeStringField("producer", car.getBrand());jsonGenerator.writeNumberField("doorCount", car.getDoors());jsonGenerator.writeEndObject();} }

運(yùn)行結(jié)果:

三)、Jackson 日期轉(zhuǎn)化

默認(rèn)情況下,Jackson會(huì)將java.util.Date對(duì)象序列化為其long型的值,該值是自1970年1月1日以來(lái)的毫秒數(shù)。但是,Jackson還支持將日期格式化為字符串。

1、Date–>long

默認(rèn)的Jackson日期格式,該格式將Date序列化為自1970年1月1日以來(lái)的毫秒數(shù)(long類型)。

這是一個(gè)包含Date字段的Java類示例:

private String type = null;private Date date = null;public Transaction() {}public Transaction(String type, Date date) {this.type = type;this.date = date;}public String getType() {return type;}public void setType(String type) {this.type = type;}public Date getDate() {return date;}public void setDate(Date date) {this.date = date;}

就像使用其他Java對(duì)象進(jìn)行序列化一樣,代碼如下:

Transaction transaction = new Transaction("transfer", new Date());ObjectMapper objectMapper = new ObjectMapper();String output = objectMapper.writeValueAsString(transaction);System.out.println(output);

運(yùn)行結(jié)果:

2、Date–>String

日期的long序列化格式不符合人類的時(shí)間查看格式。 因此,Jackson也支持文本日期格式。 可以通過(guò)在ObjectMapper上設(shè)置SimpleDateFormat來(lái)指定要使用的確切Jackson日期格式。 這是在Jackson的ObjectMapper上設(shè)置SimpleDateFormat的示例:

Transaction transaction = new Transaction("transfer", new Date());ObjectMapper objectMapper = new ObjectMapper();SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");objectMapper.setDateFormat(dateFormat);String output2 = objectMapper.writeValueAsString(transaction);System.out.println(output2);

運(yùn)行結(jié)果:

四)、Jackson JSON 樹(shù)模型

Jackson具有內(nèi)置的樹(shù)模型,可用于表示JSON對(duì)象。 如果不知道接收到的JSON的格式,或者由于某種原因而不能(或者只是不想)創(chuàng)建一個(gè)類來(lái)表示它,那么就要用到Jackson的樹(shù)模型。 如果需要在使用或轉(zhuǎn)化JSON之前對(duì)其進(jìn)行操作,也需要被用到Jackson樹(shù)模型。 所有這些情況在數(shù)據(jù)流場(chǎng)景中都很常見(jiàn)。

Jackson樹(shù)模型由JsonNode類表示。 您可以使用Jackson ObjectMapper將JSON解析為JsonNode樹(shù)模型,就像使用您自己的類一樣。

以下將展示如何使用Jackson ObjectMapper讀寫JsonNode實(shí)例。

1、Jackson Tree Model簡(jiǎn)單例子

下面是一個(gè)簡(jiǎn)單的例子:

String carJson ="{ \"brand\" : \"Mercedes\", \"doors\" : 5 }";ObjectMapper objectMapper = new ObjectMapper();try {JsonNode jsonNode = objectMapper.readValue(carJson, JsonNode.class);} catch (IOException e) {e.printStackTrace();}

只需將JsonNode.class作為第二個(gè)參數(shù)傳遞給readValue()方法,而不是本教程前面的示例中使用的Car.class,就可以將JSON字符串解析為JsonNode對(duì)象而不是Car對(duì)象。 。

ObjectMapper類還具有一個(gè)特殊的readTree()方法,該方法返回JsonNode。 這是使用ObjectMapper readTree()方法將JSON解析為JsonNode的示例:

String carJson ="{ \"brand\" : \"Mercedes\", \"doors\" : 5 }";ObjectMapper objectMapper = new ObjectMapper();try {JsonNode jsonNode = objectMapper.readTree(carJson);} catch (IOException e) {e.printStackTrace(); }

2、Jackson JsonNode類

通過(guò)JsonNode類,可以以非常靈活和動(dòng)態(tài)的方式將JSON作為Java對(duì)象導(dǎo)航。這里了解一些如何使用它的基礎(chǔ)知識(shí)。

將JSON解析為JsonNode(或JsonNode實(shí)例樹(shù))后,就可以瀏覽JsonNode樹(shù)模型。 這是一個(gè)JsonNode示例,顯示了如何訪問(wèn)JSON字段,數(shù)組和嵌套對(duì)象:

String carJson ="{ \"brand\" : \"Mercedes\", \"doors\" : 5," +" \"owners\" : [\"John\", \"Jack\", \"Jill\"]," +" \"nestedObject\" : { \"field\" : \"value\" } }";ObjectMapper objectMapper = new ObjectMapper();try {JsonNode jsonNode = objectMapper.readValue(carJson, JsonNode.class);JsonNode brandNode = jsonNode.get("brand");String brand = brandNode.asText();System.out.println("brand = " + brand);JsonNode doorsNode = jsonNode.get("doors");int doors = doorsNode.asInt();System.out.println("doors = " + doors);JsonNode array = jsonNode.get("owners");JsonNode jsonNode = array.get(0);String john = jsonNode.asText();System.out.println("john = " + john);JsonNode child = jsonNode.get("nestedObject");JsonNode childField = child.get("field");String field = childField.asText();System.out.println("field = " + field);} catch (IOException e) {e.printStackTrace(); }

請(qǐng)注意,JSON字符串現(xiàn)在包含一個(gè)稱為owners的數(shù)組字段和一個(gè)稱為nestedObject的嵌套對(duì)象字段。

無(wú)論訪問(wèn)的是字段,數(shù)組還是嵌套對(duì)象,都可以使用JsonNode類的get()方法。 通過(guò)將字符串作為參數(shù)提供給get()方法,可以訪問(wèn)JsonNode的字段。 如果JsonNode表示數(shù)組,則需要將索引傳遞給get()方法。 索引指定要獲取的數(shù)組元素。

3、Java對(duì)象–>JsonNode

可以使用Jackson ObjectMapper將Java對(duì)象轉(zhuǎn)換為JsonNode,而JsonNode是轉(zhuǎn)換后的Java對(duì)象的JSON表示形式。 可以通過(guò)Jackson ObjectMapper valueToTree()方法將Java對(duì)象轉(zhuǎn)換為JsonNode。 這是一個(gè)使用ObjectMapper valueToTree()方法將Java對(duì)象轉(zhuǎn)換為JsonNode的示例:

ObjectMapper objectMapper = new ObjectMapper();Car car = new Car(); car.brand = "Cadillac"; car.doors = 4;JsonNode carJsonNode = objectMapper.valueToTree(car);

4、JsonNode–>Java對(duì)象

可以使用Jackson ObjectMapper treeToValue()方法將JsonNode轉(zhuǎn)換為Java對(duì)象。 這類似于使用Jackson Jackson的ObjectMapper將JSON字符串(或其他來(lái)源)解析為Java對(duì)象。 唯一的區(qū)別是,JSON源是JsonNode。 這是一個(gè)使用Jackson ObjectMapper treeToValue()方法將JsonNode轉(zhuǎn)換為Java對(duì)象的示例:

ObjectMapper objectMapper = new ObjectMapper();String carJson = "{ \"brand\" : \"Mercedes\", \"doors\" : 5 }";JsonNode carJsonNode = objectMapper.readTree(carJson);Car car = objectMapper.treeToValue(carJsonNode);

上面的示例有點(diǎn)“人為”,因?yàn)槲覀兪紫葘SON字符串轉(zhuǎn)換為JsonNode,然后將JsonNode轉(zhuǎn)換為Car對(duì)象。 顯然,如果我們有對(duì)原始JSON字符串的引用,則最好將其直接轉(zhuǎn)換為Car對(duì)象,而無(wú)需先將其轉(zhuǎn)換為JsonNode。

四、JsonNode

Jackson JsonNode類com.fasterxml.jackson.databind.JsonNode是Jackson的JSON樹(shù)形模型(對(duì)象圖模型)。 Jackson可以將JSON讀取到JsonNode實(shí)例中,然后將JsonNode寫入JSON。 因此,這一節(jié)將說(shuō)明如何將JSON反序列化為JsonNode以及將JsonNode序列化為JSON。 此Jackson JsonNode教程還將說(shuō)明如何從頭開(kāi)始構(gòu)建JsonNode對(duì)象圖,因此以后可以將它們序列化為JSON。

1、JsonNode vs ObjectNode

Jackson JsonNode類是不可變的。 這意味著,實(shí)際上不能直接構(gòu)建JsonNode實(shí)例的對(duì)象圖。 而是創(chuàng)建JsonNode子類ObjectNode的對(duì)象圖。 作為JsonNode的子類,可以在可以使用JsonNode的任何地方使用ObjectNode。

2、JSON–>JsonNode

要使用Jackson將JSON讀取到JsonNode中,首先需要?jiǎng)?chuàng)建一個(gè)Jackson ObjectMapper實(shí)例。 在ObjectMapper實(shí)例上,調(diào)用readTree()并將JSON源作為參數(shù)傳遞。 這是將JSON反序列化為JsonNode的示例:

String json = "{ \"f1\" : \"v1\" } ";ObjectMapper objectMapper = new ObjectMapper();JsonNode jsonNode = objectMapper.readTree(json);System.out.println(jsonNode.get("f1").asText());

3、JsonNode–>JSON

要將Jackson的JsonNode寫入JSON,還需要一個(gè)Jackson ObjectMapper實(shí)例。 在ObjectMapper上,調(diào)用writeValueAsString()方法或任何適合需要的寫入方法。 這是將JsonNode寫入JSON的示例:

ObjectMapper objectMapper = new ObjectMapper();JsonNode jsonNode = readJsonIntoJsonNode();String json = objectMapper.writeValueAsString(jsonNode);

4、獲取JsonNode字段

JsonNode可以像JSON對(duì)象一樣具有字段。 假設(shè)已將以下JSON解析為JsonNode:

{"field1" : "value1","field2" : 999 }

此JSON對(duì)象具有兩個(gè)名為field1和field2的字段。 如果有一個(gè)表示上述JSON對(duì)象的Jackson JsonNode,則可以這樣獲得兩個(gè)字段:

JsonNode jsonNode = ... //parse above JSON into a JsonNodeJsonNode field1 = jsonNode.get("field1"); JsonNode field2 = jsonNode.get("field2");

請(qǐng)注意,即使兩個(gè)字段都是String字段,get()方法也始終返回JsonNode來(lái)表示該字段。

5、在路徑中獲取JsonNode字段

Jackson JsonNode有一個(gè)稱為at()的特殊方法。 at()方法可以從JSON圖中以給定JsonNode為根的任何位置訪問(wèn)JSON字段。 假設(shè)JSON結(jié)構(gòu)如下所示:

{"identification" : {"name" : "James","ssn: "ABC123552"} }

如果將此JSON解析為JsonNode,則可以使用at()方法訪問(wèn)名稱字段,如下所示:

JsonNode nameNode = jsonNode.at("/identification/name");

注意傳遞給at()方法的參數(shù):字符串/ identification / name。 這是一個(gè)JSON路徑表達(dá)式。 此路徑表達(dá)式指定從根JsonNode到您要訪問(wèn)其值的字段的完整路徑。 這類似于從文件系統(tǒng)根目錄到Unix文件系統(tǒng)中文件的路徑。

請(qǐng)注意,JSON路徑表達(dá)式必須以斜杠字符(/字符)開(kāi)頭。

at()方法返回一個(gè)JsonNode,它表示請(qǐng)求的JSON字段。 要獲取該字段的實(shí)際值,需要調(diào)用下一部分介紹的方法之一。 如果沒(méi)有節(jié)點(diǎn)與給定的路徑表達(dá)式匹配,則將返回null。

6、轉(zhuǎn)換JsonNode字段

Jackson JsonNode類包含一組可以將字段值轉(zhuǎn)換為另一種數(shù)據(jù)類型的方法。 例如,將String字段值轉(zhuǎn)換為long或相反。 這是將JsonNode字段轉(zhuǎn)換為一些更常見(jiàn)的數(shù)據(jù)類型的示例:

String f2Str = jsonNode.get("f2").asText(); double f2Dbl = jsonNode.get("f2").asDouble(); int f2Int = jsonNode.get("f2").asInt(); long f2Lng = jsonNode.get("f2").asLong();

使用默認(rèn)值轉(zhuǎn)換: 如果JsonNode中的字段可以為null,則在嘗試轉(zhuǎn)換它時(shí)可以提供默認(rèn)值。 這是使用默認(rèn)值調(diào)用轉(zhuǎn)換方法的示例:

ObjectMapper objectMapper = new ObjectMapper();String json = "{ \"f1\":\"Hello\", \"f2\":null }";JsonNode jsonNode = objectMapper.readTree(json);String f2Value = jsonNode.get("f2").asText("Default");

在示例的JSON字符串中可以看到,聲明了f2字段,但將其設(shè)置為null。 在這種情況下,調(diào)用jsonNode.get(“ f2”)。asText(“ Default”)將返回默認(rèn)值,在此示例中為字符串Default。

asDouble(),asInt()和asLong()方法還可以采用默認(rèn)參數(shù)值,如果嘗試從中獲取值的字段為null,則將返回默認(rèn)參數(shù)值。

請(qǐng)注意,如果該字段在JSON中未顯式設(shè)置為null,但在JSON中丟失,則調(diào)用jsonNode.get(“ fieldName”)將返回Java null值,您無(wú)法在該Java值上調(diào)用asInt() ,asDouble(),asLong()或asText()。 如果嘗試這樣做,將會(huì)導(dǎo)致NullPointerException。 這是說(shuō)明這種情況的示例:

ObjectMapper objectMapper = new ObjectMapper();String json = "{ \"f1\":\"Hello\" }";JsonNode jsonNode = objectMapper.readTree(json);JsonNode f2FieldNode = jsonNode.get("f2");

7、創(chuàng)建一個(gè)ObjectNode

如前所述,JsonNode類是不可變的。 要?jiǎng)?chuàng)建JsonNode對(duì)象圖,必須能夠更改圖中的JsonNode實(shí)例,例如 設(shè)置屬性值和子JsonNode實(shí)例等。由于是不可變的,因此無(wú)法直接使用JsonNode來(lái)實(shí)現(xiàn)。

而是創(chuàng)建一個(gè)ObjectNode實(shí)例,該實(shí)例是JsonNode的子類。 這是一個(gè)通過(guò)Jackson ObjectMapper createObjectNode()方法創(chuàng)建ObjectNode的示例:

ObjectMapper objectMapper = new ObjectMapper();ObjectNode objectNode = objectMapper.createObjectNode();

8、Set ObjectNode字段

要在Jackson ObjectNode上設(shè)置字段,可以調(diào)用其set()方法,并將字段名稱String和JsonNode作為參數(shù)傳遞。 這是在Jackson的ObjectNode上設(shè)置字段的示例:

ObjectMapper objectMapper = new ObjectMapper(); ObjectNode parentNode = objectMapper.createObjectNode();JsonNode childNode = readJsonIntoJsonNode();parentNode.set("child1", childNode);

9、Put ObjectNode字段

ObjectNode類還具有一組方法,可以直接為字段put(設(shè)置)值。 這比嘗試將原始值轉(zhuǎn)換為JsonNode并使用set()進(jìn)行設(shè)置要容易得多。 以下是使用put()方法為ObjectNode上的字段設(shè)置字符串值的示例:

objectNode.put("field1", "value1"); objectNode.put("field2", 123); objectNode.put("field3", 999.999);

10、刪除字段

ObjectNode類具有一個(gè)稱為remove()的方法,該方法可用于從ObjectNode中刪除字段。 這是一個(gè)通過(guò)其remove()方法從Jackson ObjectNode刪除字段的示例:

objectNode.remove("fieldName");

11、循環(huán)JsonNode字段

JsonNode類具有一個(gè)名為fieldNames()的方法,該方法返回一個(gè)Iterator,可以迭代JsonNode的所有字段名稱。 我們可以使用字段名稱來(lái)獲取字段值。 這是一個(gè)迭代Jackson JsonNode的所有字段名稱和值的示例:

Iterator<String> fieldNames = jsonNode.fieldNames();while(fieldNames.hasNext()) {String fieldName = fieldNames.next();JsonNode field = jsonNode.get(fieldName); }

五、JsonParser

Jackson JsonParser類是一個(gè)底層一些的JSON解析器。 它類似于XML的Java StAX解析器,差別是JsonParser解析JSON而不解析XML。

Jackson JsonParser的運(yùn)行層級(jí)低于Jackson ObjectMapper。 這使得JsonParser比ObjectMapper更快,但使用起來(lái)也比較麻煩。

1、創(chuàng)建一個(gè)JsonParser

為了創(chuàng)建Jackson JsonParser,首先需要?jiǎng)?chuàng)建一個(gè)JsonFactory。 JsonFactory用于創(chuàng)建JsonParser實(shí)例。 JsonFactory類包含幾個(gè)createParser()方法,每個(gè)方法都使用不同的JSON源作為參數(shù)。

這是創(chuàng)建一個(gè)JsonParser來(lái)從字符串中解析JSON的示例:

String carJson ="{ \"brand\" : \"Mercedes\", \"doors\" : 5 }";JsonFactory factory = new JsonFactory(); JsonParser parser = factory.createParser(carJson);

2、用JsonParser轉(zhuǎn)化JSON

一旦創(chuàng)建了Jackson JsonParser,就可以使用它來(lái)解析JSON。 JsonParser的工作方式是將JSON分解為一系列令牌,可以一個(gè)一個(gè)地迭代令牌。

這是一個(gè)JsonParser示例,它簡(jiǎn)單地循環(huán)遍歷所有標(biāo)記并將它們輸出到System.out。 這是一個(gè)實(shí)際上很少用示例,只是展示了將JSON分解成的令牌,以及如何遍歷令牌的基礎(chǔ)知識(shí)。

tring carJson ="{ \"brand\" : \"Mercedes\", \"doors\" : 5 }";JsonFactory factory = new JsonFactory(); JsonParser parser = factory.createParser(carJson);while(!parser.isClosed()){JsonToken jsonToken = parser.nextToken();System.out.println("jsonToken = " + jsonToken); }

只要JsonParser的isClosed()方法返回false,那么JSON源中仍然會(huì)有更多的令牌。

可以使用JsonParser的nextToken()獲得一個(gè)JsonToken。 您可以使用此JsonToken實(shí)例檢查給定的令牌。 令牌類型由JsonToken類中的一組常量表示。 這些常量是:

START_OBJECT END_OBJECT START_ARRAY END_ARRAY FIELD_NAME VALUE_EMBEDDED_OBJECT VALUE_FALSE VALUE_TRUE VALUE_NULL VALUE_STRING VALUE_NUMBER_INT VALUE_NUMBER_FLOAT

可以使用這些常量來(lái)找出當(dāng)前JsonToken是什么類型的令牌。 可以通過(guò)這些常量的equals()方法進(jìn)行操作。 這是一個(gè)例子:

String carJson ="{ \"brand\" : \"Mercedes\", \"doors\" : 5 }";JsonFactory factory = new JsonFactory(); JsonParser parser = factory.createParser(carJson);Car car = new Car(); while(!parser.isClosed()){JsonToken jsonToken = parser.nextToken();if(JsonToken.FIELD_NAME.equals(jsonToken)){String fieldName = parser.getCurrentName();System.out.println(fieldName);jsonToken = parser.nextToken();if("brand".equals(fieldName)){car.brand = parser.getValueAsString();} else if ("doors".equals(fieldName)){car.doors = parser.getValueAsInt();}} }System.out.println("car.brand = " + car.brand); System.out.println("car.doors = " + car.doors);

如果指向的標(biāo)記是字段名稱,則JsonParser的getCurrentName()方法將返回當(dāng)前字段名稱。

如果指向的令牌是字符串字段值,則getValueAsString()返回當(dāng)前令牌值作為字符串。 如果指向的令牌是整數(shù)字段值,則getValueAsInt()返回當(dāng)前令牌值作為int值。 JsonParser具有更多類似的方法來(lái)獲取不同類型的curren令牌值(例如boolean,short,long,float,double等)。

六、JsonGenerator

Jackson JsonGenerator用于從Java對(duì)象(或代碼從中生成JSON的任何數(shù)據(jù)結(jié)構(gòu))生成JSON。

1、創(chuàng)建一個(gè)JsonGenerator

為了創(chuàng)建Jackson JsonGenerator,必須首先創(chuàng)建JsonFactory實(shí)例。 這是創(chuàng)建JsonFactory的方法:

JsonFactory factory = new JsonFactory();

一旦創(chuàng)建了JsonFactory,就可以使用JsonFactory的createGenerator()方法創(chuàng)建JsonGenerator。 這是創(chuàng)建JsonGenerator的示例:

JsonFactory factory = new JsonFactory();JsonGenerator generator = factory.createGenerator(new File("data/output.json"), JsonEncoding.UTF8);

createGenerator()方法的第一個(gè)參數(shù)是生成的JSON的目標(biāo)。 在上面的示例中,參數(shù)是File對(duì)象。 這意味著生成的JSON將被寫入給定文件。 createGenerator()方法已重載,因此還有其他版本的createGenerator()方法采用例如OutputStream等,提供了有關(guān)將生成的JSON寫入何處的不同選項(xiàng)。

createGenerator()方法的第二個(gè)參數(shù)是生成JSON時(shí)使用的字符編碼。 上面的示例使用UTF-8。

2、使用JsonGenerator生成JSON

一旦創(chuàng)建了JsonGenerator,就可以開(kāi)始生成JSON。 JsonGenerator包含一組write …()方法,可以使用這些方法來(lái)編寫JSON對(duì)象的各個(gè)部分。 這是一個(gè)使用Jackson JsonGenerator生成JSON的簡(jiǎn)單示例:

JsonFactory factory = new JsonFactory();JsonGenerator generator = factory.createGenerator(new File("data/output.json"), JsonEncoding.UTF8);generator.writeStartObject(); generator.writeStringField("brand", "Mercedes"); generator.writeNumberField("doors", 5); generator.writeEndObject();generator.close();

此示例首先調(diào)用writeStartObject(),將{寫入輸出。 然后,該示例調(diào)用writeStringField(),將品牌字段名稱+值寫入輸出。 之后,將調(diào)用writeNumberField()方法,此方法會(huì)將Doors字段名稱+值寫入輸出。 最后,調(diào)用writeEndObject(),將}寫入輸出。

JsonGenerator還可以使用許多其他寫入方法。 這個(gè)例子只顯示了其中一些。

3、關(guān)閉JsonGenerator

完成生成JSON后,應(yīng)關(guān)閉JsonGenerator。 您可以通過(guò)調(diào)用其close()方法來(lái)實(shí)現(xiàn)。 這是關(guān)閉JsonGenerator的樣子:

generator.close();

七、Jackson注解

Jackson JSON工具包包含一組Java注解,可以使用這些注解來(lái)設(shè)置將JSON讀入對(duì)象的方式或從對(duì)象生成什么JSON的方式。 此Jackson注解教程介紹了如何使用Jackson的注解。

下面是一些常用的注解:

注解用法
@JsonProperty用于屬性,把屬性的名稱序列化時(shí)轉(zhuǎn)換為另外一個(gè)名稱。示例: @JsonProperty(“birth_ d ate”) private Date birthDate;
@JsonFormat用于屬性或者方法,把屬性的格式序列化時(shí)轉(zhuǎn)換成指定的格式。示例: @JsonFormat(timezone = “GMT+8”, pattern = “yyyy-MM-dd HH:mm”) public Date getBirthDate()
@JsonPropertyOrder用于類, 指定屬性在序列化時(shí) json 中的順序 , 示例: @JsonPropertyOrder({ “birth_Date”, “name” }) public class Person
@JsonCreator用于構(gòu)造方法,和 @JsonProperty 配合使用,適用有參數(shù)的構(gòu)造方法。 示例: @JsonCreator public Person(@JsonProperty(“name”)String name) {…}
@JsonAnySetter用于屬性或者方法,設(shè)置未反序列化的屬性名和值作為鍵值存儲(chǔ)到 map 中 @JsonAnySetter public void set(String key, Object value) { map.put(key, value); }
@JsonAnyGetter用于方法 ,獲取所有未序列化的屬性 public Map<String, Object> any() { return map; }

下面是一些注解的詳細(xì)說(shuō)明。

一)、Read + Write注解

Jackson包含一組注解,這些注解會(huì)影響從JSON讀取Java對(duì)象以及將Java對(duì)象寫入JSON。 我將這些注解稱為“讀+寫注解”。 以下各節(jié)將更詳細(xì)地介紹Jackson的讀寫注解。

1、@JsonIgnore

Jackson注解@JsonIgnore用于告訴Jackson忽略Java對(duì)象的某個(gè)屬性(字段)。 在將JSON讀取到Java對(duì)象中以及將Java對(duì)象寫入JSON時(shí),都將忽略該屬性。

這是使用@JsonIgnore注解的示例:

import com.fasterxml.jackson.annotation.JsonIgnore;public class PersonIgnore {@JsonIgnorepublic long personId = 0;public String name = null; }

在上面的類中,不會(huì)從JSON讀取或?qū)懭隞SON屬性personId。

2、@JsonIgnoreProperties

@JsonIgnoreProperties Jackson注解用于指定要忽略的類的屬性列表。 @JsonIgnoreProperties注解放置在類聲明上方,而不是要忽略的各個(gè)屬性(字段)上方。

這是如何使用@JsonIgnoreProperties注解的示例:

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;@JsonIgnoreProperties({"firstName", "lastName"}) public class PersonIgnoreProperties {public long personId = 0;public String firstName = null;public String lastName = null;}

在此示例中,屬性firstName和lastName都將被忽略,因?yàn)樗鼈兊拿Q在類聲明上方的@JsonIgnoreProperties注解聲明內(nèi)列出。

3、@JsonIgnoreType

@JsonIgnoreType Jackson注解用于將整個(gè)類型(類)標(biāo)記為在使用該類型的任何地方都將被忽略。

這是一個(gè)示例,展示如何使用@JsonIgnoreType注解:

import com.fasterxml.jackson.annotation.JsonIgnoreType;public class PersonIgnoreType {@JsonIgnoreTypepublic static class Address {public String streetName = null;public String houseNumber = null;public String zipCode = null;public String city = null;public String country = null;}public long personId = 0;public String name = null;public Address address = null; }

在上面的示例中,所有Address實(shí)例將被忽略。

4、@JsonAutoDetect

Jackson注解@JsonAutoDetect用于告訴Jackson在讀寫對(duì)象時(shí)包括非public修飾的屬性。

這是一個(gè)示例類,展示如何使用@JsonAutoDetect注解:

import com.fasterxml.jackson.annotation.JsonAutoDetect;@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY ) public class PersonAutoDetect {private long personId = 123;public String name = null;}

JsonAutoDetect.Visibility類包含與Java中的可見(jiàn)性級(jí)別匹配的常量,表示ANY,DEFAULT,NON_PRIVATE,NONE,PROTECTED_AND_PRIVATE和PUBLIC_ONLY。

二)、Read注解

Jackson包含一組注解,這些注解僅影響Jackson將JSON解析為對(duì)象的方式-意味著它們影響Jackson對(duì)JSON的讀取。 我稱這些為“讀注解”。 以下各節(jié)介紹了Jackson的讀注解。

1、@JsonSetter

Jackson注解@JsonSetter用于告訴Jackson,當(dāng)將JSON讀入對(duì)象時(shí),應(yīng)將此setter方法的名稱與JSON數(shù)據(jù)中的屬性名稱匹配。 如果Java類內(nèi)部使用的屬性名稱與JSON文件中使用的屬性名稱不同,這個(gè)注解就很有用了。

以下Person類用personId名稱對(duì)應(yīng)JSON中名為id的字段:

public class Person {private long personId = 0;private String name = null;public long getPersonId() { return this.personId; }public void setPersonId(long personId) { this.personId = personId; }public String getName() { return name; }public void setName(String name) { this.name = name; } }

但是在此JSON對(duì)象中,使用名稱id代替personId:

{"id" : 1234,"name" : "John" }

Jackson無(wú)法將id屬性從JSON對(duì)象映射到Java類的personId字段。

@JsonSetter注解指示Jackson為給定的JSON字段使用setter方法。 在我們的示例中,我們?cè)趕etPersonId()方法上方添加@JsonSetter注解。

這是添加@JsonSetter注解的實(shí)例:

public class Person {private long personId = 0;private String name = null;public long getPersonId() { return this.personId; }@JsonSetter("id")public void setPersonId(long personId) { this.personId = personId; }public String getName() { return name; }public void setName(String name) { this.name = name; } }

@JsonSetter注解中指定的值是要與此setter方法匹配的JSON字段的名稱。 在這種情況下,名稱為id,因?yàn)檫@是我們要映射到setPersonId()setter方法的JSON對(duì)象中字段的名稱。

2、@JsonAnySetter

Jackson注解@JsonAnySetter表示Jackson為JSON對(duì)象中所有無(wú)法識(shí)別的字段調(diào)用相同的setter方法。 “無(wú)法識(shí)別”是指尚未映射到Java對(duì)象中的屬性或設(shè)置方法的所有字段。

看一下這個(gè)Bag類:

public class Bag {private Map<String, Object> properties = new HashMap<>();public void set(String fieldName, Object value){this.properties.put(fieldName, value);}public Object get(String fieldName){return this.properties.get(fieldName);} }

然后查看此JSON對(duì)象:

{"id" : 1234,"name" : "John" }

Jackson無(wú)法直接將此JSON對(duì)象的id和name屬性映射到Bag類,因?yàn)锽ag類不包含任何公共字段或setter方法。

可以通過(guò)添加@JsonAnySetter注解來(lái)告訴Jackson為所有無(wú)法識(shí)別的字段調(diào)用set()方法,如下所示:

public class Bag {private Map<String, Object> properties = new HashMap<>();@JsonAnySetterpublic void set(String fieldName, Object value){this.properties.put(fieldName, value);}public Object get(String fieldName){return this.properties.get(fieldName);} }

現(xiàn)在,Jackson將使用JSON對(duì)象中所有無(wú)法識(shí)別的字段的名稱和值調(diào)用set()方法。

請(qǐng)記住,這僅對(duì)無(wú)法識(shí)別的字段有效。 例如,如果您向Bag Java類添加了公共名稱屬性或setName(String)方法,則JSON對(duì)象中的名稱字段將改為映射到該屬性/設(shè)置器。

3、@JsonCreator

Jackson注解@JsonCreator用于告訴Jackson該Java對(duì)象具有一個(gè)構(gòu)造函數(shù)(“創(chuàng)建者”),該構(gòu)造函數(shù)可以將JSON對(duì)象的字段與Java對(duì)象的字段進(jìn)行匹配。

@JsonCreator注解在無(wú)法使用@JsonSetter注解的情況下很有用。 例如,不可變對(duì)象沒(méi)有任何設(shè)置方法,因此它們需要將其初始值注入到構(gòu)造函數(shù)中。

以這個(gè)PersonImmutable類為例:

public class PersonImmutable {private long id = 0;private String name = null;public PersonImmutable(long id, String name) {this.id = id;this.name = name;}public long getId() {return id;}public String getName() {return name;}}

要告訴Jackson應(yīng)該調(diào)用PersonImmutable的構(gòu)造函數(shù),我們必須在構(gòu)造函數(shù)中添加@JsonCreator注解。 但是,僅憑這一點(diǎn)還不夠。 我們還必須注解構(gòu)造函數(shù)的參數(shù),以告訴Jackson將JSON對(duì)象中的哪些字段傳遞給哪些構(gòu)造函數(shù)參數(shù)。

添加了@JsonCreator和@JsonProperty注解的PersonImmutable類的示例如下:

public class PersonImmutable {private long id = 0;private String name = null;@JsonCreatorpublic PersonImmutable(@JsonProperty("id") long id,@JsonProperty("name") String name ) {this.id = id;this.name = name;}public long getId() {return id;}public String getName() {return name;}}

請(qǐng)注意,構(gòu)造函數(shù)上方的注解以及構(gòu)造函數(shù)參數(shù)之前的注解。 現(xiàn)在,Jackson能夠從此JSON對(duì)象創(chuàng)建PersonImmutable:

{"id" : 1234,"name" : "John" }

4、@JacksonInject

Jackson注解@JacksonInject用于將值注入到解析的對(duì)象中,而不是從JSON中讀取這些值。 例如,假設(shè)正在從各種不同的源下載Person JSON對(duì)象,并且想知道給定Person對(duì)象來(lái)自哪個(gè)源。 源本身可能不包含該信息,但是可以讓Jackson將其注入到根據(jù)JSON對(duì)象創(chuàng)建的Java對(duì)象中。

要將Java類中的字段標(biāo)記為需要由Jackson注入其值的字段,請(qǐng)?jiān)谠撟侄紊戏教砑?#64;JacksonInject注解。

這是一個(gè)示例PersonInject類,在屬性上方添加了@JacksonInject注解:

public class PersonInject {public long id = 0;public String name = null;@JacksonInjectpublic String source = null;}

為了讓Jackson將值注入屬性,需要在創(chuàng)建Jackson ObjectMapper時(shí)做一些額外的工作。

這是讓Jackson將值注入Java對(duì)象的過(guò)程:

InjectableValues inject = new InjectableValues.Std().addValue(String.class, "jenkov.com"); PersonInject personInject = new ObjectMapper().reader(inject).forType(PersonInject.class).readValue(new File("data/person.json"));

請(qǐng)注意,如何在InjectableValues addValue()方法中設(shè)置要注入到source屬性中的值。 還要注意,該值僅綁定到字符串類型-而不綁定到任何特定的字段名稱。 @JacksonInject注解指定將值注入到哪個(gè)字段。

如果要從多個(gè)源下載人員JSON對(duì)象,并為每個(gè)源注入不同的源值,則必須為每個(gè)源重復(fù)以上代碼。

5、@JsonDeserialize

Jackson注解@JsonDeserialize用于為Java對(duì)象中給定的屬性指定自定義反序列化器類。

例如,假設(shè)想優(yōu)化布爾值false和true的在線格式,使其分別為0和1。

首先,需要將@JsonDeserialize注解添加到要為其使用自定義反序列化器的字段。 這是將@JsonDeserialize注解添加到字段的示例:

public class PersonDeserialize {public long id = 0;public String name = null;@JsonDeserialize(using = OptimizedBooleanDeserializer.class)public boolean enabled = false; }

其次,這是@JsonDeserialize注解中引用的OptimizedBooleanDeserializer類的實(shí)例:

public class OptimizedBooleanDeserializerextends JsonDeserializer<Boolean> {@Overridepublic Boolean deserialize(JsonParser jsonParser,DeserializationContext deserializationContext) throwsIOException, JsonProcessingException {String text = jsonParser.getText();if("0".equals(text)) return false;return true;} }

請(qǐng)注意,OptimizedBooleanDeserializer類使用通用類型Boolean擴(kuò)展了JsonDeserializer。 這樣做會(huì)使deserialize()方法返回一個(gè)布爾對(duì)象。 如果要反序列化其他類型(例如java.util.Date),則必須在泛型括號(hào)內(nèi)指定該類型。

可以通過(guò)調(diào)用jsonParser參數(shù)的getText()方法來(lái)獲取要反序列化的字段的值。 然后,可以將該文本反序列化為任何值,然后輸入反序列化程序所針對(duì)的類型(在此示例中為布爾值)。

最后,需要查看使用自定義反序列化器和@JsonDeserializer注解反序列化對(duì)象的格式:

PersonDeserialize person = objectMapper.reader(PersonDeserialize.class).readValue(new File("data/person-optimized-boolean.json"));

注意,我們首先需要如何使用ObjectMapper的reader()方法為PersonDeserialize類創(chuàng)建一個(gè)閱讀器,然后在該方法返回的對(duì)象上調(diào)用readValue()。

三)、Write注解

Jackson還包含一組注解,這些注解可以影響Jackson將Java對(duì)象序列化(寫入)到JSON的方式。 以下各節(jié)將介紹這些寫(序列化)注解中的每一個(gè)。

1、@JsonInclude

Jackson注解@JsonInclude告訴Jackson僅在某些情況下包括屬性。 例如,僅當(dāng)屬性為非null,非空或具有非默認(rèn)值時(shí),才應(yīng)包括該屬性。 這是顯示如何使用@JsonInclude注解的示例:

import com.fasterxml.jackson.annotation.JsonInclude;@JsonInclude(JsonInclude.Include.NON_EMPTY) public class PersonInclude {public long personId = 0;public String name = null;}

如果為該示例設(shè)置的值是非空的,則此示例將僅包括name屬性,這意味著不為null且不是空字符串。

@JsonInclude注解的一個(gè)更通俗的名稱應(yīng)該是@JsonIncludeOnlyWhen,但是寫起來(lái)會(huì)更長(zhǎng)。

2、@JsonGetter

@JsonGetter Jackson注解用于告訴Jackson,應(yīng)該通過(guò)調(diào)用getter方法而不是通過(guò)直接字段訪問(wèn)來(lái)獲取某個(gè)字段值。 如果您的Java類使用jQuery樣式的getter和setter名稱,則@JsonGetter注解很有用。

例如,您可能擁有方法personId()和personId(long id),而不是getPersonId()和setPersonId()。

這是一個(gè)名為PersonGetter的示例類,它顯示了@JsonGetter注解的用法:

public class PersonGetter {private long personId = 0;@JsonGetter("id")public long personId() { return this.personId; }@JsonSetter("id")public void personId(long personId) { this.personId = personId; }}

如您所見(jiàn),personId()方法帶有@JsonGetter注解。 @JsonGetter注解上設(shè)置的值是JSON對(duì)象中應(yīng)使用的名稱。 因此,用于JSON對(duì)象中personId的名稱是id。 生成的JSON對(duì)象如下所示:

{"id":0}

還要注意,personId(long personId)方法使用@JsonSetter注解進(jìn)行注解,以使Jackson識(shí)別為與JSON對(duì)象中的id屬性匹配的設(shè)置方法。 從JSON讀取Java對(duì)象時(shí)使用@JsonSetter注解-將Java對(duì)象寫入JSON時(shí)不使用。 為了完整起見(jiàn),僅包含@JsonSetter注解。

3、@JsonAnyGetter

@JsonAnyGetter Jackson注解使您可以將Map用作要序列化為JSON的屬性的容器。 這是在Java類中使用@JsonAnyGetter注解的示例:

public class PersonAnyGetter {private Map<String, Object> properties = new HashMap<>();@JsonAnyGetterpublic Map<String, Object> properties() {return properties;} }

當(dāng)看到@JsonAnyGetter注解時(shí),Jackson將從@JsonAnyGetter注解的方法中獲取返回的Map,并將該Map中的每個(gè)鍵值對(duì)都視為一個(gè)屬性。 換句話說(shuō),Map中的所有鍵值對(duì)都將作為PersonAnyGetter對(duì)象的一部分序列化為JSON。

4、@JsonPropertyOrder

@JsonPropertyOrder Jackson注解可用于指定將Java對(duì)象的字段序列化為JSON的順序。 這是顯示如何使用@JsonPropertyOrder注解的示例:

@JsonPropertyOrder({"name", "personId"}) public class PersonPropertyOrder {public long personId = 0;public String name = null;}

通常,Jackson會(huì)按照在類中找到的順序序列化PersonPropertyOrder中的屬性。 但是,@JsonPropertyOrder注解指定了不同的順序,在序列化的JSON輸出中,name屬性將首先出現(xiàn),personId屬性將隨后出現(xiàn)。

5、@JsonRawValue

@JsonRawValue Jackson注解告訴Jackson該屬性值應(yīng)直接寫入JSON輸出。 如果該屬性是字符串,Jackson通常會(huì)將值括在引號(hào)中,但是如果使用@JsonRawValue屬性進(jìn)行注解,Jackson將不會(huì)這樣做。

為了更清楚@JsonRawValue的作用,看看沒(méi)有使用@JsonRawValue的此類:

public class PersonRawValue {public long personId = 0;public String address = "$#"; }

Jackson會(huì)將其序列化為以下JSON字符串:

{"personId":0,"address":"$#"}

現(xiàn)在,我們將@JsonRawValue添加到address屬性,如下所示:

public class PersonRawValue {public long personId = 0;@JsonRawValuepublic String address = "$#"; }

現(xiàn)在,當(dāng)對(duì)地址屬性進(jìn)行序列化時(shí),杰克遜將省略引號(hào)。 因此,序列化的JSON如下所示:

{"personId":0,"address":$#}

當(dāng)然它是無(wú)效的JSON,那么為什么要這么做呢?

如果address屬性包含一個(gè)JSON字符串,那么該JSON字符串將被序列化為最終的JSON對(duì)象,作為JSON對(duì)象結(jié)構(gòu)的一部分,而不僅是序列化為JSON對(duì)象的address字段中的字符串。

要查看其工作原理,讓我們像下面這樣更改address屬性的值:

public class PersonRawValue {public long personId = 0;@JsonRawValuepublic String address ="{ \"street\" : \"Wall Street\", \"no\":1}";}

Jackson會(huì)將其序列化為以下JSON:

{"personId":0,"address":{ "street" : "Wall Street", "no":1}}

請(qǐng)注意,JSON字符串現(xiàn)在如何成為序列化JSON結(jié)構(gòu)的一部分。

沒(méi)有@JsonRawValue注解,Jackson會(huì)將對(duì)象序列化為以下JSON:

{"personId":0,"address":"{ \"street\" : \"Wall Street\", \"no\":1}"}

請(qǐng)注意,address屬性的值現(xiàn)在如何用引號(hào)引起來(lái),并且值內(nèi)的所有引號(hào)均被轉(zhuǎn)義。

6、@JsonValue

Jackson注解@JsonValue告訴Jackson,Jackson不應(yīng)該嘗試序列化對(duì)象本身,而應(yīng)在對(duì)象上調(diào)用將對(duì)象序列化為JSON字符串的方法。 請(qǐng)注意,Jackson將在自定義序列化返回的String內(nèi)轉(zhuǎn)義任何引號(hào),因此不能返回例如 完整的JSON對(duì)象。 為此,應(yīng)該改用@JsonRawValue(請(qǐng)參閱上一節(jié))。

@JsonValue注解已添加到Jackson調(diào)用的方法中,以將對(duì)象序列化為JSON字符串。 這是顯示如何使用@JsonValue注解的示例:

public class PersonValue {public long personId = 0;public String name = null;@JsonValuepublic String toJson(){return this.personId + "," + this.name;}}

要求Jackson序列化PersonValue對(duì)象所得到的輸出是:

"0,null"

引號(hào)由Jackson添加。 請(qǐng)記住,對(duì)象返回的值字符串中的所有引號(hào)均會(huì)轉(zhuǎn)義。

7、@JsonSerialize

@JsonSerialize Jackson注解用于為Java對(duì)象中的字段指定自定義序列化程序。 這是一個(gè)使用@JsonSerialize注解的Java類示例:

public class PersonSerializer {public long personId = 0;public String name = "John";@JsonSerialize(using = OptimizedBooleanSerializer.class)public boolean enabled = false; }

注意啟用字段上方的@JsonSerialize注解。

OptimizedBooleanSerializer將序列的真值序列化為1,將假值序列化為0。這是代碼:

public class OptimizedBooleanSerializer extends JsonSerializer<Boolean> {@Overridepublic void serialize(Boolean aBoolean, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {if(aBoolean){jsonGenerator.writeNumber(1);} else {jsonGenerator.writeNumber(0);}} }

總結(jié)

以上是生活随笔為你收集整理的Jackson用法详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。