Spring MVC 默認採用Jackson解析Json,儘管還有一些其它一樣優秀的json解析工具,例如Fast Json、GSON,可是出於最小依賴的考慮,也許Json解析第一選擇就應該是Jackson。html
Jackson 是當前用的比較普遍的,用來序列化和反序列化 json 的 Java 的開源框架。Jackson 社區相對比較活躍,更新速度也比較快, 從 Github 中的統計來看,Jackson 是最流行的 json 解析器之一 。 Spring MVC 的默認 json 解析器即是 Jackson。 Jackson 優勢不少。 Jackson 所依賴的 jar 包較少 ,簡單易用。與其餘 Java 的 json 的框架 Gson 等相比, Jackson 解析大的 json 文件速度比較快;Jackson 運行時佔用內存比較低,性能比較好;Jackson 有靈活的 API,能夠很容易進行擴展和定製。java
Jackson 的 1.x 版本的包名是 org.codehaus.jackson ,當升級到 2.x 版本時,包名變爲 com.fasterxml.jackson。node
Jackson 的核心模塊由三部分組成。git
源碼地址:FasterXML/jacksongithub
使用Maven構建項目,須要添加依賴:json
<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>
複製代碼
固然了,jackson-databind 依賴 jackson-core 和 jackson-annotations,因此能夠只顯示地添加jackson-databind依賴,jackson-core 和 jackson-annotations 也隨之添加到 Java 項目工程中。數組
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.6</version>
</dependency>
複製代碼
下面是Jackson的用法。數據結構
Jackson 最經常使用的 API 就是基於"對象綁定" 的 ObjectMapper:app
ObjectMapper能夠從字符串,流或文件中解析JSON,並建立表示已解析的JSON的Java對象。 將JSON解析爲Java對象也稱爲從JSON反序列化Java對象。框架
ObjectMapper也能夠從Java對象建立JSON。 從Java對象生成JSON也稱爲將Java對象序列化爲JSON。
Object映射器能夠將JSON解析爲自定義的類的對象,也能夠解析置JSON樹模型的對象。
之因此稱爲ObjectMapper是由於它將JSON映射到Java對象(反序列化),或者將Java對象映射到JSON(序列化)。
一個簡單的例子:
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轉換爲Car類對象:
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();
}
複製代碼
默認狀況下,Jackson經過將JSON字段的名稱與Java對象中的getter和setter方法進行匹配,將JSON對象的字段映射到Java對象中的屬性。 Jackson刪除了getter和setter方法名稱的「 get」和「 set」部分,並將其他名稱的第一個字符轉換爲小寫。
例如,名爲brand的JSON字段與名爲getBrand()和setBrand()的Java getter和setter方法匹配。 名爲engineNumber的JSON字段將與名爲getEngineNumber()和setEngineNumber()的getter和setter匹配。
若是須要以其餘方式將JSON對象字段與Java對象字段匹配,則須要使用自定義序列化器和反序列化器,或者使用一些Jackson註解。
從JSON字符串讀取Java對象很是容易。 上面已經有了一個示例——JSON字符串做爲第一個參數傳遞給ObjectMapper的readValue()方法。 這是另外一個簡單的示例:
ObjectMapper objectMapper = new ObjectMapper();
String carJson =
"{ \"brand\" : \"Mercedes\", \"doors\" : 5 }";
Car car = objectMapper.readValue(carJson, Car.class);
複製代碼
還能夠從經過Reader實例加載的JSON中讀取對象。示例以下:
ObjectMapper objectMapper = new ObjectMapper();
String carJson =
"{ \"brand\" : \"Mercedes\", \"doors\" : 4 }";
Reader reader = new StringReader(carJson);
Car car = objectMapper.readValue(reader, Car.class);
複製代碼
從文件讀取JSON固然能夠經過FileReader(而不是StringReader)來完成,也能夠經過File對象來完成。 這是從文件讀取JSON的示例:
ObjectMapper objectMapper = new ObjectMapper();
File file = new File("data/car.json");
Car car = objectMapper.readValue(file, Car.class);
複製代碼
能夠經過URL(java.net.URL)從JSON讀取對象,以下所示:
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)。
也可使用ObjectMapper經過InputStream從JSON讀取對象。 這是一個從InputStream讀取JSON的示例:
ObjectMapper objectMapper = new ObjectMapper();
InputStream input = new FileInputStream("data/car.json");
Car car = objectMapper.readValue(input, Car.class);
複製代碼
Jackson還支持從JSON字節數組讀取對象。 這是從JSON字節數組讀取對象的示例:
ObjectMapper objectMapper = new ObjectMapper();
String carJson =
"{ \"brand\" : \"Mercedes\", \"doors\" : 5 }";
byte[] bytes = carJson.getBytes("UTF-8");
Car car = objectMapper.readValue(bytes, Car.class);
複製代碼
Jackson ObjectMapper也能夠從JSON數組字符串讀取對象數組。 這是從JSON數組字符串讀取對象數組的示例:
String jsonArray = "[{\"brand\":\"ford\"}, {\"brand\":\"Fiat\"}]";
ObjectMapper objectMapper = new ObjectMapper();
Car[] cars2 = objectMapper.readValue(jsonArray, Car[].class);
複製代碼
須要將Car數組類做爲第二個參數傳遞給readValue()方法。
讀取對象數組還能夠與字符串之外的其餘JSON源一塊兒使用。 例如,文件,URL,InputStream,Reader等。
Jackson ObjectMapper還能夠從JSON數組字符串讀取對象的Java List。 這是從JSON數組字符串讀取對象列表的示例:
String jsonArray = "[{\"brand\":\"ford\"}, {\"brand\":\"Fiat\"}]";
ObjectMapper objectMapper = new ObjectMapper();
List<Car> cars1 = objectMapper.readValue(jsonArray, new TypeReference<List<Car>>(){});
複製代碼
Jackson ObjectMapper還能夠從JSON字符串讀取Java Map。 若是事先不知道將要解析的確切JSON結構,這種方法是頗有用的。 一般,會將JSON對象讀入Java Map。 JSON對象中的每一個字段都將成爲Java Map中的鍵,值對。
這是一個使用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>>(){});
複製代碼
有時候,與要從JSON讀取的Java對象相比,JSON中的字段更多。 默認狀況下,Jackson在這種狀況下會拋出異常,報不知道XYZ字段異常,由於在Java對象中找不到該字段。
可是,有時應該容許JSON中的字段多於相應的Java對象中的字段。 例如,要從REST服務解析JSON,而該REST服務包含的數據遠遠超出所需的。 在這種狀況下,可使用Jackson配置忽略這些額外的字段。 如下是配置Jackson ObjectMapper忽略未知字段的示例:
objectMapper.configure(
DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
複製代碼
若是JSON字符串包含其值設置爲null的字段(對於在相應的Java對象中是基本數據類型(int,long,float,double等)的字段),Jackson ObjectMapper默認會處理基本數據類型爲null的狀況,咱們能夠能夠將Jackson ObjectMapper默認配置爲失效,這樣基本數據爲null就會轉換失敗。 例如如下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字段是一個int類型,它是Java中的基本數據類型。
如今,假設有一個與Car對象相對應的JSON字符串,以下所示:
{ "brand":"Toyota", "doors":null }
複製代碼
請注意,doors字段值爲null。 Java中的基本數據類型不能爲null值。 默認狀況下,Jackson ObjectMapper會忽略原始字段的空值。 可是,能夠將Jackson ObjectMapper配置設置爲失敗。
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, true);
複製代碼
在FAIL_ON_NULL_FOR_PRIMITIVES配置值設置爲true的狀況下,嘗試將空JSON字段解析爲基本類型Java字段時會遇到異常。 這是一個Java Jackson ObjectMapper示例,該示例將失敗,由於JSON字段包含原始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);
複製代碼
結果:
有時,可能但願以不一樣於Jackson ObjectMapper缺省方式的方式將JSON字符串讀入Java對象。 能夠將自定義反序列化器添加到ObjectMapper,能夠按須要執行反序列化。
這是在Jackson的ObjectMapper中註冊和使用自定義反序列化器的方式:
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);
}
@Override
public 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;
}
}
複製代碼
Jackson ObjectMapper也能夠用於從對象生成JSON。 可使用如下方法之一進行操做:
這是一個從Car對象生成JSON的示例,和上面的實例相反:
ObjectMapper objectMapper = new ObjectMapper();
Car car = new Car();
car.setBrand("BMW");
car.setDoors(4);
objectMapper.writeValue(
new FileOutputStream("data/output-2.json"), car);
複製代碼
此示例首先建立一個ObjectMapper,而後建立一個Car實例,最後調用ObjectMapper的writeValue()方法,該方法將Car對象轉換爲JSON並將其寫入給定的FileOutputStream。
ObjectMapper的writeValueAsString()和writeValueAsBytes()都從一個對象生成JSON,並將生成的JSON做爲String或字節數組返回。 示例以下:
ObjectMapper objectMapper = new ObjectMapper();
Car car = new Car();
car.setBrand("寶馬");
car.setDoors(4);
String json = objectMapper.writeValueAsString(car);
System.out.println(json);
複製代碼
運行結果:
有時,想要將Java對象序列化爲JSON的方式與使用Jackson的默認方式不一樣。 例如,可能想要在JSON中使用與Java對象中不一樣的字段名稱,或者但願徹底省略某些字段。
Jackson能夠在ObjectMapper上設置自定義序列化器。 該序列化器已爲某個類註冊,而後在每次要求ObjectMapper序列化Car對象時將調用該序列化器。
這是爲Car類註冊自定義序列化器的示例:
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();
}
}
複製代碼
運行結果:
默認狀況下,Jackson會將java.util.Date對象序列化爲其long型的值,該值是自1970年1月1日以來的毫秒數。可是,Jackson還支持將日期格式化爲字符串。
默認的Jackson日期格式,該格式將Date序列化爲自1970年1月1日以來的毫秒數(long類型)。
這是一個包含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對象進行序列化同樣,代碼以下:
Transaction transaction = new Transaction("transfer", new Date());
ObjectMapper objectMapper = new ObjectMapper();
String output = objectMapper.writeValueAsString(transaction);
System.out.println(output);
複製代碼
運行結果:
日期的long序列化格式不符合人類的時間查看格式。 所以,Jackson也支持文本日期格式。 能夠經過在ObjectMapper上設置SimpleDateFormat來指定要使用的確切Jackson日期格式。 這是在Jackson的ObjectMapper上設置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);
複製代碼
運行結果:
Jackson具備內置的樹模型,可用於表示JSON對象。 若是不知道接收到的JSON的格式,或者因爲某種緣由而不能(或者只是不想)建立一個類來表示它,那麼就要用到Jackson的樹模型。 若是須要在使用或轉化JSON以前對其進行操做,也須要被用到Jackson樹模型。 全部這些狀況在數據流場景中都很常見。
Jackson樹模型由JsonNode類表示。 您可使用Jackson ObjectMapper將JSON解析爲JsonNode樹模型,就像使用您本身的類同樣。
如下將展現如何使用Jackson ObjectMapper讀寫JsonNode實例。
下面是一個簡單的例子:
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做爲第二個參數傳遞給readValue()方法,而不是本教程前面的示例中使用的Car.class,就能夠將JSON字符串解析爲JsonNode對象而不是Car對象。 。
ObjectMapper類還具備一個特殊的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();
}
複製代碼
經過JsonNode類,能夠以很是靈活和動態的方式將JSON做爲Java對象導航。這裏瞭解一些如何使用它的基礎知識。
將JSON解析爲JsonNode(或JsonNode實例樹)後,就能夠瀏覽JsonNode樹模型。 這是一個JsonNode示例,顯示瞭如何訪問JSON字段,數組和嵌套對象:
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();
}
複製代碼
請注意,JSON字符串如今包含一個稱爲owners的數組字段和一個稱爲nestedObject的嵌套對象字段。
不管訪問的是字段,數組仍是嵌套對象,均可以使用JsonNode類的get()方法。 經過將字符串做爲參數提供給get()方法,能夠訪問JsonNode的字段。 若是JsonNode表示數組,則須要將索引傳遞給get()方法。 索引指定要獲取的數組元素。
可使用Jackson ObjectMapper將Java對象轉換爲JsonNode,而JsonNode是轉換後的Java對象的JSON表示形式。 能夠經過Jackson ObjectMapper valueToTree()方法將Java對象轉換爲JsonNode。 這是一個使用ObjectMapper valueToTree()方法將Java對象轉換爲JsonNode的示例:
ObjectMapper objectMapper = new ObjectMapper();
Car car = new Car();
car.brand = "Cadillac";
car.doors = 4;
JsonNode carJsonNode = objectMapper.valueToTree(car);
複製代碼
可使用Jackson ObjectMapper treeToValue()方法將JsonNode轉換爲Java對象。 這相似於使用Jackson Jackson的ObjectMapper將JSON字符串(或其餘來源)解析爲Java對象。 惟一的區別是,JSON源是JsonNode。 這是一個使用Jackson ObjectMapper treeToValue()方法將JsonNode轉換爲Java對象的示例:
ObjectMapper objectMapper = new ObjectMapper();
String carJson = "{ \"brand\" : \"Mercedes\", \"doors\" : 5 }";
JsonNode carJsonNode = objectMapper.readTree(carJson);
Car car = objectMapper.treeToValue(carJsonNode);
複製代碼
上面的示例有點「人爲」,由於咱們首先將JSON字符串轉換爲JsonNode,而後將JsonNode轉換爲Car對象。 顯然,若是咱們有對原始JSON字符串的引用,則最好將其直接轉換爲Car對象,而無需先將其轉換爲JsonNode。
Jackson JsonNode類com.fasterxml.jackson.databind.JsonNode是Jackson的JSON樹形模型(對象圖模型)。 Jackson能夠將JSON讀取到JsonNode實例中,而後將JsonNode寫入JSON。 所以,這一節將說明如何將JSON反序列化爲JsonNode以及將JsonNode序列化爲JSON。 此Jackson JsonNode教程還將說明如何從頭開始構建JsonNode對象圖,所以之後能夠將它們序列化爲JSON。
Jackson JsonNode類是不可變的。 這意味着,實際上不能直接構建JsonNode實例的對象圖。 而是建立JsonNode子類ObjectNode的對象圖。 做爲JsonNode的子類,能夠在可使用JsonNode的任何地方使用ObjectNode。
要使用Jackson將JSON讀取到JsonNode中,首先須要建立一個Jackson ObjectMapper實例。 在ObjectMapper實例上,調用readTree()並將JSON源做爲參數傳遞。 這是將JSON反序列化爲JsonNode的示例:
String json = "{ \"f1\" : \"v1\" } ";
ObjectMapper objectMapper = new ObjectMapper();
JsonNode jsonNode = objectMapper.readTree(json);
System.out.println(jsonNode.get("f1").asText());
複製代碼
要將Jackson的JsonNode寫入JSON,還須要一個Jackson ObjectMapper實例。 在ObjectMapper上,調用writeValueAsString()方法或任何適合須要的寫入方法。 這是將JsonNode寫入JSON的示例:
ObjectMapper objectMapper = new ObjectMapper();
JsonNode jsonNode = readJsonIntoJsonNode();
String json = objectMapper.writeValueAsString(jsonNode);
複製代碼
JsonNode能夠像JSON對象同樣具備字段。 假設已將如下JSON解析爲JsonNode:
{
"field1" : "value1",
"field2" : 999
}
複製代碼
此JSON對象具備兩個名爲field1和field2的字段。 若是有一個表示上述JSON對象的Jackson JsonNode,則能夠這樣得到兩個字段:
JsonNode jsonNode = ... //parse above JSON into a JsonNode
JsonNode field1 = jsonNode.get("field1");
JsonNode field2 = jsonNode.get("field2");
複製代碼
請注意,即便兩個字段都是String字段,get()方法也始終返回JsonNode來表示該字段。
Jackson JsonNode有一個稱爲at()的特殊方法。 at()方法能夠從JSON圖中以給定JsonNode爲根的任何位置訪問JSON字段。 假設JSON結構以下所示:
{
"identification" : {
"name" : "James",
"ssn: "ABC123552"
}
}
複製代碼
若是將此JSON解析爲JsonNode,則可使用at()方法訪問名稱字段,以下所示:
JsonNode nameNode = jsonNode.at("/identification/name");
複製代碼
注意傳遞給at()方法的參數:字符串/ identification / name。 這是一個JSON路徑表達式。 此路徑表達式指定從根JsonNode到您要訪問其值的字段的完整路徑。 這相似於從文件系統根目錄到Unix文件系統中文件的路徑。
請注意,JSON路徑表達式必須以斜槓字符(/字符)開頭。
at()方法返回一個JsonNode,它表示請求的JSON字段。 要獲取該字段的實際值,須要調用下一部分介紹的方法之一。 若是沒有節點與給定的路徑表達式匹配,則將返回null。
Jackson JsonNode類包含一組能夠將字段值轉換爲另外一種數據類型的方法。 例如,將String字段值轉換爲long或相反。 這是將JsonNode字段轉換爲一些更常見的數據類型的示例:
String f2Str = jsonNode.get("f2").asText();
double f2Dbl = jsonNode.get("f2").asDouble();
int f2Int = jsonNode.get("f2").asInt();
long f2Lng = jsonNode.get("f2").asLong();
複製代碼
使用默認值轉換: 若是JsonNode中的字段能夠爲null,則在嘗試轉換它時能夠提供默認值。 這是使用默認值調用轉換方法的示例:
ObjectMapper objectMapper = new ObjectMapper();
String json = "{ \"f1\":\"Hello\", \"f2\":null }";
JsonNode jsonNode = objectMapper.readTree(json);
String f2Value = jsonNode.get("f2").asText("Default");
複製代碼
在示例的JSON字符串中能夠看到,聲明瞭f2字段,但將其設置爲null。 在這種狀況下,調用jsonNode.get(「 f2」)。asText(「 Default」)將返回默認值,在此示例中爲字符串Default。
asDouble(),asInt()和asLong()方法還能夠採用默認參數值,若是嘗試從中獲取值的字段爲null,則將返回默認參數值。
請注意,若是該字段在JSON中未顯式設置爲null,但在JSON中丟失,則調用jsonNode.get(「 fieldName」)將返回Java null值,您沒法在該Java值上調用asInt() ,asDouble(),asLong()或asText()。 若是嘗試這樣作,將會致使NullPointerException。 這是說明這種狀況的示例:
ObjectMapper objectMapper = new ObjectMapper();
String json = "{ \"f1\":\"Hello\" }";
JsonNode jsonNode = objectMapper.readTree(json);
JsonNode f2FieldNode = jsonNode.get("f2");
複製代碼
如前所述,JsonNode類是不可變的。 要建立JsonNode對象圖,必須可以更改圖中的JsonNode實例,例如 設置屬性值和子JsonNode實例等。因爲是不可變的,所以沒法直接使用JsonNode來實現。
而是建立一個ObjectNode實例,該實例是JsonNode的子類。 這是一個經過Jackson ObjectMapper createObjectNode()方法建立ObjectNode的示例:
ObjectMapper objectMapper = new ObjectMapper();
ObjectNode objectNode = objectMapper.createObjectNode();
複製代碼
要在Jackson ObjectNode上設置字段,能夠調用其set()方法,並將字段名稱String和JsonNode做爲參數傳遞。 這是在Jackson的ObjectNode上設置字段的示例:
ObjectMapper objectMapper = new ObjectMapper();
ObjectNode parentNode = objectMapper.createObjectNode();
JsonNode childNode = readJsonIntoJsonNode();
parentNode.set("child1", childNode);
複製代碼
ObjectNode類還具備一組方法,能夠直接爲字段put(設置)值。 這比嘗試將原始值轉換爲JsonNode並使用set()進行設置要容易得多。 如下是使用put()方法爲ObjectNode上的字段設置字符串值的示例:
objectNode.put("field1", "value1");
objectNode.put("field2", 123);
objectNode.put("field3", 999.999);
複製代碼
ObjectNode類具備一個稱爲remove()的方法,該方法可用於從ObjectNode中刪除字段。 這是一個經過其remove()方法從Jackson ObjectNode刪除字段的示例:
objectNode.remove("fieldName");
複製代碼
JsonNode類具備一個名爲fieldNames()的方法,該方法返回一個Iterator,能夠迭代JsonNode的全部字段名稱。 咱們可使用字段名稱來獲取字段值。 這是一個迭代Jackson JsonNode的全部字段名稱和值的示例:
Iterator<String> fieldNames = jsonNode.fieldNames();
while(fieldNames.hasNext()) {
String fieldName = fieldNames.next();
JsonNode field = jsonNode.get(fieldName);
}
複製代碼
Jackson JsonParser類是一個底層一些的JSON解析器。 它相似於XML的Java StAX解析器,差異是JsonParser解析JSON而不解析XML。
Jackson JsonParser的運行層級低於Jackson ObjectMapper。 這使得JsonParser比ObjectMapper更快,但使用起來也比較麻煩。
爲了建立Jackson JsonParser,首先須要建立一個JsonFactory。 JsonFactory用於建立JsonParser實例。 JsonFactory類包含幾個createParser()方法,每一個方法都使用不一樣的JSON源做爲參數。
這是建立一個JsonParser來從字符串中解析JSON的示例:
String carJson =
"{ \"brand\" : \"Mercedes\", \"doors\" : 5 }";
JsonFactory factory = new JsonFactory();
JsonParser parser = factory.createParser(carJson);
複製代碼
一旦建立了Jackson JsonParser,就可使用它來解析JSON。 JsonParser的工做方式是將JSON分解爲一系列令牌,能夠一個一個地迭代令牌。
這是一個JsonParser示例,它簡單地循環遍歷全部標記並將它們輸出到System.out。 這是一個實際上不多用示例,只是展現了將JSON分解成的令牌,以及如何遍歷令牌的基礎知識。
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源中仍然會有更多的令牌。
可使用JsonParser的nextToken()得到一個JsonToken。 您可使用此JsonToken實例檢查給定的令牌。 令牌類型由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
複製代碼
可使用這些常量來找出當前JsonToken是什麼類型的令牌。 能夠經過這些常量的equals()方法進行操做。 這是一個例子:
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);
複製代碼
若是指向的標記是字段名稱,則JsonParser的getCurrentName()方法將返回當前字段名稱。
若是指向的令牌是字符串字段值,則getValueAsString()返回當前令牌值做爲字符串。 若是指向的令牌是整數字段值,則getValueAsInt()返回當前令牌值做爲int值。 JsonParser具備更多相似的方法來獲取不一樣類型的curren令牌值(例如boolean,short,long,float,double等)。
Jackson JsonGenerator用於從Java對象(或代碼從中生成JSON的任何數據結構)生成JSON。
爲了建立Jackson JsonGenerator,必須首先建立JsonFactory實例。 這是建立JsonFactory的方法:
JsonFactory factory = new JsonFactory();
複製代碼
一旦建立了JsonFactory,就可使用JsonFactory的createGenerator()方法建立JsonGenerator。 這是建立JsonGenerator的示例:
JsonFactory factory = new JsonFactory();
JsonGenerator generator = factory.createGenerator(
new File("data/output.json"), JsonEncoding.UTF8);
複製代碼
createGenerator()方法的第一個參數是生成的JSON的目標。 在上面的示例中,參數是File對象。 這意味着生成的JSON將被寫入給定文件。 createGenerator()方法已重載,所以還有其餘版本的createGenerator()方法採用例如OutputStream等,提供了有關將生成的JSON寫入何處的不一樣選項。
createGenerator()方法的第二個參數是生成JSON時使用的字符編碼。 上面的示例使用UTF-8。
一旦建立了JsonGenerator,就能夠開始生成JSON。 JsonGenerator包含一組write ...()方法,可使用這些方法來編寫JSON對象的各個部分。 這是一個使用Jackson JsonGenerator生成JSON的簡單示例:
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();
複製代碼
此示例首先調用writeStartObject(),將{寫入輸出。 而後,該示例調用writeStringField(),將品牌字段名稱+值寫入輸出。 以後,將調用writeNumberField()方法,此方法會將Doors字段名稱+值寫入輸出。 最後,調用writeEndObject(),將}寫入輸出。
JsonGenerator還可使用許多其餘寫入方法。 這個例子只顯示了其中一些。
完成生成JSON後,應關閉JsonGenerator。 您能夠經過調用其close()方法來實現。 這是關閉JsonGenerator的樣子:
generator.close();
複製代碼
Jackson JSON工具包包含一組Java註解,可使用這些註解來設置將JSON讀入對象的方式或從對象生成什麼JSON的方式。 此Jackson註解教程介紹瞭如何使用Jackson的註解。
下面是一些經常使用的註解:
註解 | 用法 |
---|---|
@JsonProperty | 用於屬性,把屬性的名稱序列化時轉換爲另一個名稱。示例: @JsonProperty("birth_ d ate") private Date birthDate; |
@JsonFormat | 用於屬性或者方法,把屬性的格式序列化時轉換成指定的格式。示例: @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm") public Date getBirthDate() |
@JsonPropertyOrder | 用於類, 指定屬性在序列化時 json 中的順序 , 示例: @JsonPropertyOrder({ "birth_Date", "name" }) public class Person |
@JsonCreator | 用於構造方法,和 @JsonProperty 配合使用,適用有參數的構造方法。 示例: @JsonCreator public Person(@JsonProperty("name")String name) {…} |
@JsonAnySetter | 用於屬性或者方法,設置未反序列化的屬性名和值做爲鍵值存儲到 map 中 @JsonAnySetter public void set(String key, Object value) { map.put(key, value); } |
@JsonAnyGetter | 用於方法 ,獲取全部未序列化的屬性 public Map<String, Object> any() { return map; } |
下面是一些註解的詳細說明。
Jackson包含一組註解,這些註解會影響從JSON讀取Java對象以及將Java對象寫入JSON。 我將這些註解稱爲「讀+寫註解」。 如下各節將更詳細地介紹Jackson的讀寫註解。
Jackson註解@JsonIgnore用於告訴Jackson忽略Java對象的某個屬性(字段)。 在將JSON讀取到Java對象中以及將Java對象寫入JSON時,都將忽略該屬性。
這是使用@JsonIgnore註解的示例:
import com.fasterxml.jackson.annotation.JsonIgnore;
public class PersonIgnore {
@JsonIgnore
public long personId = 0;
public String name = null;
}
複製代碼
在上面的類中,不會從JSON讀取或寫入JSON屬性personId。
@JsonIgnoreProperties Jackson註解用於指定要忽略的類的屬性列表。 @JsonIgnoreProperties註解放置在類聲明上方,而不是要忽略的各個屬性(字段)上方。
這是如何使用@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都將被忽略,由於它們的名稱在類聲明上方的@JsonIgnoreProperties註解聲明內列出。
@JsonIgnoreType Jackson註解用於將整個類型(類)標記爲在使用該類型的任何地方都將被忽略。
這是一個示例,展現如何使用@JsonIgnoreType註解:
import com.fasterxml.jackson.annotation.JsonIgnoreType;
public class PersonIgnoreType {
@JsonIgnoreType
public 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實例將被忽略。
Jackson註解@JsonAutoDetect用於告訴Jackson在讀寫對象時包括非public修飾的屬性。
這是一個示例類,展現如何使用@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中的可見性級別匹配的常量,表示ANY,DEFAULT,NON_PRIVATE,NONE,PROTECTED_AND_PRIVATE和PUBLIC_ONLY。
Jackson包含一組註解,這些註解僅影響Jackson將JSON解析爲對象的方式-意味着它們影響Jackson對JSON的讀取。 我稱這些爲「讀註解」。 如下各節介紹了Jackson的讀註解。
Jackson註解@JsonSetter用於告訴Jackson,當將JSON讀入對象時,應將此setter方法的名稱與JSON數據中的屬性名稱匹配。 若是Java類內部使用的屬性名稱與JSON文件中使用的屬性名稱不一樣,這個註解就頗有用了。
如下Person類用personId名稱對應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對象中,使用名稱id代替personId:
{
"id" : 1234,
"name" : "John"
}
複製代碼
Jackson沒法將id屬性從JSON對象映射到Java類的personId字段。
@JsonSetter註解指示Jackson爲給定的JSON字段使用setter方法。 在咱們的示例中,咱們在setPersonId()方法上方添加@JsonSetter註解。
這是添加@JsonSetter註解的實例:
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,由於這是咱們要映射到setPersonId()setter方法的JSON對象中字段的名稱。
Jackson註解@JsonAnySetter表示Jackson爲JSON對象中全部沒法識別的字段調用相同的setter方法。 「沒法識別」是指還沒有映射到Java對象中的屬性或設置方法的全部字段。
看一下這個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對象:
{
"id" : 1234,
"name" : "John"
}
複製代碼
Jackson沒法直接將此JSON對象的id和name屬性映射到Bag類,由於Bag類不包含任何公共字段或setter方法。
能夠經過添加@JsonAnySetter註解來告訴Jackson爲全部沒法識別的字段調用set()方法,以下所示:
public class Bag {
private Map<String, Object> properties = new HashMap<>();
@JsonAnySetter
public void set(String fieldName, Object value){
this.properties.put(fieldName, value);
}
public Object get(String fieldName){
return this.properties.get(fieldName);
}
}
複製代碼
如今,Jackson將使用JSON對象中全部沒法識別的字段的名稱和值調用set()方法。
請記住,這僅對沒法識別的字段有效。 例如,若是您向Bag Java類添加了公共名稱屬性或setName(String)方法,則JSON對象中的名稱字段將改成映射到該屬性/設置器。
Jackson註解@JsonCreator用於告訴Jackson該Java對象具備一個構造函數(「建立者」),該構造函數能夠將JSON對象的字段與Java對象的字段進行匹配。
@JsonCreator註解在沒法使用@JsonSetter註解的狀況下頗有用。 例如,不可變對象沒有任何設置方法,所以它們須要將其初始值注入到構造函數中。
以這個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應該調用PersonImmutable的構造函數,咱們必須在構造函數中添加@JsonCreator註解。 可是,僅憑這一點還不夠。 咱們還必須註解構造函數的參數,以告訴Jackson將JSON對象中的哪些字段傳遞給哪些構造函數參數。
添加了@JsonCreator和@JsonProperty註解的PersonImmutable類的示例以下:
public class PersonImmutable {
private long id = 0;
private String name = null;
@JsonCreator
public 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;
}
}
複製代碼
請注意,構造函數上方的註解以及構造函數參數以前的註解。 如今,Jackson可以今後JSON對象建立PersonImmutable:
{
"id" : 1234,
"name" : "John"
}
複製代碼
Jackson註解@JacksonInject用於將值注入到解析的對象中,而不是從JSON中讀取這些值。 例如,假設正在從各類不一樣的源下載Person JSON對象,而且想知道給定Person對象來自哪一個源。 源自己可能不包含該信息,可是可讓Jackson將其注入到根據JSON對象建立的Java對象中。
要將Java類中的字段標記爲須要由Jackson注入其值的字段,請在該字段上方添加@JacksonInject註解。
這是一個示例PersonInject類,在屬性上方添加了@JacksonInject註解:
public class PersonInject {
public long id = 0;
public String name = null;
@JacksonInject
public String source = null;
}
複製代碼
爲了讓Jackson將值注入屬性,須要在建立Jackson ObjectMapper時作一些額外的工做。
這是讓Jackson將值注入Java對象的過程:
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"));
複製代碼
請注意,如何在InjectableValues addValue()方法中設置要注入到source屬性中的值。 還要注意,該值僅綁定到字符串類型-而不綁定到任何特定的字段名稱。 @JacksonInject註解指定將值注入到哪一個字段。
若是要從多個源下載人員JSON對象,併爲每一個源注入不一樣的源值,則必須爲每一個源重複以上代碼。
Jackson註解@JsonDeserialize用於爲Java對象中給定的屬性指定自定義反序列化器類。
例如,假設想優化布爾值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類的實例:
public class OptimizedBooleanDeserializer extends JsonDeserializer<Boolean> {
@Override
public Boolean deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
String text = jsonParser.getText();
if("0".equals(text)) return false;
return true;
}
}
複製代碼
請注意,OptimizedBooleanDeserializer類使用通用類型Boolean擴展了JsonDeserializer。 這樣作會使deserialize()方法返回一個布爾對象。 若是要反序列化其餘類型(例如java.util.Date),則必須在泛型括號內指定該類型。
能夠經過調用jsonParser參數的getText()方法來獲取要反序列化的字段的值。 而後,能夠將該文本反序列化爲任何值,而後輸入反序列化程序所針對的類型(在此示例中爲布爾值)。
最後,須要查看使用自定義反序列化器和@JsonDeserializer註解反序列化對象的格式:
PersonDeserialize person = objectMapper
.reader(PersonDeserialize.class)
.readValue(new File("data/person-optimized-boolean.json"));
複製代碼
注意,咱們首先須要如何使用ObjectMapper的reader()方法爲PersonDeserialize類建立一個閱讀器,而後在該方法返回的對象上調用readValue()。
Jackson還包含一組註解,這些註解能夠影響Jackson將Java對象序列化(寫入)到JSON的方式。 如下各節將介紹這些寫(序列化)註解中的每個。
Jackson註解@JsonInclude告訴Jackson僅在某些狀況下包括屬性。 例如,僅當屬性爲非null,非空或具備非默認值時,才應包括該屬性。 這是顯示如何使用@JsonInclude註解的示例:
import com.fasterxml.jackson.annotation.JsonInclude;
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class PersonInclude {
public long personId = 0;
public String name = null;
}
複製代碼
若是爲該示例設置的值是非空的,則此示例將僅包括name屬性,這意味着不爲null且不是空字符串。
@JsonInclude註解的一個更通俗的名稱應該是@JsonIncludeOnlyWhen,可是寫起來會更長。
@JsonGetter Jackson註解用於告訴Jackson,應該經過調用getter方法而不是經過直接字段訪問來獲取某個字段值。 若是您的Java類使用jQuery樣式的getter和setter名稱,則@JsonGetter註解頗有用。
例如,您可能擁有方法personId()和personId(long id),而不是getPersonId()和setPersonId()。
這是一個名爲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; }
}
複製代碼
如您所見,personId()方法帶有@JsonGetter註解。 @JsonGetter註解上設置的值是JSON對象中應使用的名稱。 所以,用於JSON對象中personId的名稱是id。 生成的JSON對象以下所示:
{"id":0}
複製代碼
還要注意,personId(long personId)方法使用@JsonSetter註解進行註解,以使Jackson識別爲與JSON對象中的id屬性匹配的設置方法。 從JSON讀取Java對象時使用@JsonSetter註解-將Java對象寫入JSON時不使用。 爲了完整起見,僅包含@JsonSetter註解。
@JsonAnyGetter Jackson註解使您能夠將Map用做要序列化爲JSON的屬性的容器。 這是在Java類中使用@JsonAnyGetter註解的示例:
public class PersonAnyGetter {
private Map<String, Object> properties = new HashMap<>();
@JsonAnyGetter
public Map<String, Object> properties() {
return properties;
}
}
複製代碼
當看到@JsonAnyGetter註解時,Jackson將從@JsonAnyGetter註解的方法中獲取返回的Map,並將該Map中的每一個鍵值對都視爲一個屬性。 換句話說,Map中的全部鍵值對都將做爲PersonAnyGetter對象的一部分序列化爲JSON。
@JsonPropertyOrder Jackson註解可用於指定將Java對象的字段序列化爲JSON的順序。 這是顯示如何使用@JsonPropertyOrder註解的示例:
@JsonPropertyOrder({"name", "personId"})
public class PersonPropertyOrder {
public long personId = 0;
public String name = null;
}
複製代碼
一般,Jackson會按照在類中找到的順序序列化PersonPropertyOrder中的屬性。 可是,@JsonPropertyOrder註解指定了不一樣的順序,在序列化的JSON輸出中,name屬性將首先出現,personId屬性將隨後出現。
@JsonRawValue Jackson註解告訴Jackson該屬性值應直接寫入JSON輸出。 若是該屬性是字符串,Jackson一般會將值括在引號中,可是若是使用@JsonRawValue屬性進行註解,Jackson將不會這樣作。
爲了更清楚@JsonRawValue的做用,看看沒有使用@JsonRawValue的此類:
public class PersonRawValue {
public long personId = 0;
public String address = "$#";
}
複製代碼
Jackson會將其序列化爲如下JSON字符串:
{"personId":0,"address":"$#"}
複製代碼
如今,咱們將@JsonRawValue添加到address屬性,以下所示:
public class PersonRawValue {
public long personId = 0;
@JsonRawValue
public String address = "$#";
}
複製代碼
如今,當對地址屬性進行序列化時,傑克遜將省略引號。 所以,序列化的JSON以下所示:
{"personId":0,"address":$#}
複製代碼
固然它是無效的JSON,那麼爲何要這麼作呢?
若是address屬性包含一個JSON字符串,那麼該JSON字符串將被序列化爲最終的JSON對象,做爲JSON對象結構的一部分,而不只是序列化爲JSON對象的address字段中的字符串。
要查看其工做原理,讓咱們像下面這樣更改address屬性的值:
public class PersonRawValue {
public long personId = 0;
@JsonRawValue
public String address =
"{ \"street\" : \"Wall Street\", \"no\":1}";
}
複製代碼
Jackson會將其序列化爲如下JSON:
{"personId":0,"address":{ "street" : "Wall Street", "no":1}}
複製代碼
請注意,JSON字符串如今如何成爲序列化JSON結構的一部分。
沒有@JsonRawValue註解,Jackson會將對象序列化爲如下JSON:
{"personId":0,"address":"{ \"street\" : \"Wall Street\", \"no\":1}"}
複製代碼
請注意,address屬性的值如今如何用引號引發來,而且值內的全部引號均被轉義。
Jackson註解@JsonValue告訴Jackson,Jackson不該該嘗試序列化對象自己,而應在對象上調用將對象序列化爲JSON字符串的方法。 請注意,Jackson將在自定義序列化返回的String內轉義任何引號,所以不能返回例如 完整的JSON對象。 爲此,應該改用@JsonRawValue(請參閱上一節)。
@JsonValue註解已添加到Jackson調用的方法中,以將對象序列化爲JSON字符串。 這是顯示如何使用@JsonValue註解的示例:
public class PersonValue {
public long personId = 0;
public String name = null;
@JsonValue
public String toJson(){
return this.personId + "," + this.name;
}
}
複製代碼
要求Jackson序列化PersonValue對象所獲得的輸出是:
"0,null"
複製代碼
引號由Jackson添加。 請記住,對象返回的值字符串中的全部引號均會轉義。
@JsonSerialize Jackson註解用於爲Java對象中的字段指定自定義序列化程序。 這是一個使用@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> {
@Override
public void serialize(Boolean aBoolean, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
if(aBoolean){
jsonGenerator.writeNumber(1);
} else {
jsonGenerator.writeNumber(0);
}
}
}
複製代碼
參考:
【1】:Jackson Installation 【2】:Jackson ObjectMapper 【3】:Jackson 框架的高階應用 【4】:Jackson JsonNode 【5】:Jackson JsonParser 【6】:Jackson JsonGenerator 【7】:Jackson Annotations