文章目錄
-
- json說明
-
- JSON 文法規則
- JSON 值
- JSON 對象
- JSON 數組
- Jackson的使用
-
- Jackson的注解使用
-
- 序列化注解
-
- @JsonAnyGetter
- @JsonGetter
- @JsonPropertyOrder
- @JsonRawValue
- @JsonValue
- @JsonRootName
- @JsonSerialize
- 反序列化注解
-
- @JsonCreator
- @JacksonInject
- @JsonAnySetter
- @JsonSetter
- @JsonDeserialize
- @JsonAlias
- Jackson 屬性包含有關的注釋
-
- @JsonIgnoreProperties
- @JsonIgnore
- @JsonIgnoreType
- @JsonInclude
- @JsonAutoDetect
- Jackson 多态類型處理注解
- Jackson 一般注釋
-
- @JsonProperty
- @JsonFormat
- @JsonUnwrapped
- @JsonView
- 三種方式處理JSON
- Jackson ObjectMapper
-
- 使用ObjectMapper讀寫
- Java 對象到 JSON
-
- writeValue
- writeValueAsString
- writeValueAsBytes
- JSON 到 Java 對象
-
- readValue
- JSON 到 Jackson JsonNode
- 從 JSON 數組字元串建立 Java List
- 從 JSON 字元串建立 Java Map
- 進階功能
-
- 配置序列化或反序列化功能
- 建立自定義序列化程式或反序列化程式
- 處理日期格式
json說明
JSON(JavaScript Object Notation)是一種輕量級的、 完全獨立于語言的文本格式。
JSON 的兩種結構:
- 名稱/值對的集合。在各種語言中,這被實作為對象、記錄、結構、字典、哈希表、鍵控清單或關聯數組。
- 值的有序清單。在大多數語言中,這被實作為數組、向量、清單或序列。
JSON 文法規則
JSON 文法是 JavaScript 對象表示文法的子集。
- 大括号 {} 儲存對象
- 中括号 [] 儲存數組,數組可以包含多個對象
JSON 值
JSON 值可以是:
- 數字(整數或浮點數)
- 字元串(在雙引号中)
- 邏輯值(true 或 false)
- 數組(在中括号中)
- 對象(在大括号中)
- null
JSON 對象
key 必須是字元串,value 可以是合法的 JSON 資料類型(字元串, 數字, 對象, 數組, 布爾值或 null)。
JSON 數組
[
{ key1 : value1-1 , key2:value1-2 },
{ key1 : value2-1 , key2:value2-2 },
{ key1 : value3-1 , key2:value3-2 },
...
{ keyN : valueN-1 , keyN:valueN-2 },
]
Jackson的使用
jackson序列化對象時,隻序列化非私有字段和帶有getter\setter的私有字段。
Jackson的注解使用
序列化注解
@JsonAnyGetter
該注釋允許靈活地使用 Map 字段作為标準屬性。
實體類:
package com.yongren.jsonAnnotation;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import java.util.HashMap;
import java.util.Map;
public class ExtendableBean {
private String name;
protected Map<String, String> properties = new HashMap<>();
public ExtendableBean(String name) {
this.name = name;
}
@JsonAnyGetter
public Map<String, String> getProperties() {
return properties;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
測試類:
public void whenSerializingUsingJsonAnyGetter_thenCorrect()
throws JsonProcessingException {
ExtendableBean bean = new ExtendableBean("My bean");
Map<String, String> map = bean.getProperties();
map.put("attr1", "val1");
map.put("attr2", "val2");
ObjectMapper objectMapper = new ObjectMapper();
String result = objectMapper.writeValueAsString(bean);
System.out.println(result);
}
使用@JsonAnyGetter的結果
不使用的結果:
@JsonGetter
該注解是 @JsonProperty 替代方法,用于将方法标記為 getter 方法
package com.yongren.jsonAnnotation;
import com.fasterxml.jackson.annotation.JsonGetter;
public class MyBean {
public int id;
private String name ;
@JsonGetter("name")
public String getTheName() {
return name;
}
public MyBean(int id, String name) {
this.id = id;
this.name = name;
}
}
測試類:
@Test
public void whenSerializingUsingJsonGetter_thenCorrect()
throws JsonProcessingException {
MyBean bean = new MyBean(1, "My bean");
String result = new ObjectMapper().writeValueAsString(bean);
System.out.println(result);
}
測試結果
@JsonPropertyOrder
我們可以使用@JsonPropertyOrder 注釋來指定序列化屬性的順序。
實體類:
package com.yongren.jsonAnnotation;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
@JsonPropertyOrder({ "name", "id" })
public class MyBean2 {
public int id;
public String name;
public MyBean2(int id, String name) {
this.id = id;
this.name = name;
}
}
測試方法:
@Test
void whenSerializingUsingJsonPropertyOrder_thenCorrect() throws JsonProcessingException {
MyBean2 bean = new MyBean2(1, "My bean");
String result = new ObjectMapper().writeValueAsString(bean);
System.out.println(result);
}
使用注解測試結果:
不使用,測試結果:
@JsonRawValue
該@JsonRawValue注釋可以訓示傑克遜序列化的屬性完全一樣的
package com.yongren.jsonAnnotation;
import com.fasterxml.jackson.annotation.JsonRawValue;
public class RawBean {
public String name;
@JsonRawValue
public String json;
public RawBean(String name, String json) {
this.name = name;
this.json = json;
}
}
測試方法:
@Test
public void whenSerializingUsingJsonRawValue_thenCorrect()
throws JsonProcessingException {
RawBean bean = new RawBean("My bean", "{\"attr\":false}");
String result = new ObjectMapper().writeValueAsString(bean);
System.out.println(result);
}
使用注解結果:
不用的結果:
@JsonValue
@JsonValue訓示序列化所有執行個體使用的單個方法。
實體類:
package com.yongren.jsonAnnotation;
import com.fasterxml.jackson.annotation.JsonValue;
public enum TypeEnumWithValue {
TYPE1(1, "Type A"), TYPE2(2, "Type 2");
private Integer id;
private String name;
// standard constructors
TypeEnumWithValue(Integer id, String name) {
this.id = id;
this.name = name;
}
@JsonValue
public String getName() {
return name;
}
}
測試:
@Test
public void whenSerializingUsingJsonValue_thenCorrect()
throws JsonParseException, IOException {
String enumAsString = new ObjectMapper()
.writeValueAsString(TypeEnumWithValue.TYPE1);
System.out.println(enumAsString);
}
使用結果:
不使用,則直接輸出Enum執行個體的名稱
@JsonRootName
使用@JsonRootName 注釋,如果啟用了包裝
mapper.enable(SerializationFeature.WRAP_ROOT_VALUE)
——會将實體序列化對象包裝在指定的對象中
實體類:
package com.yongren.jsonAnnotation;
import com.fasterxml.jackson.annotation.JsonRootName;
@JsonRootName(value = "yongren")
public class UserWithRoot {
public int id;
public String name;
public UserWithRoot(int id, String name) {
this.id = id;
this.name = name;
}
}
測試方法:
@Test
public void whenSerializingUsingJsonRootName_thenCorrect()
throws JsonProcessingException {
UserWithRoot user = new UserWithRoot(1, "John");
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
String result = mapper.writeValueAsString(user);
System.out.println(result);
}
使用,結果:
@JsonSerialize
@JsonSerialize表示在編組實體時使用自定義序列化程式。
jackson在序列化時間Date類型時,會序列化成毫秒,指定自定義序列器,來指定時間格式。
實體:
package com.yongren.jsonAnnotation;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class EventWithSerializer {
public String name;
@JsonSerialize(using = CustomDateSerializer.class)
public Date eventDate;
public EventWithSerializer(String name, Date eventDate) {
this.name = name;
this.eventDate = eventDate;
}
}
class CustomDateSerializer extends StdSerializer<Date> {
private static SimpleDateFormat formatter
= new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
public CustomDateSerializer() {
this(null);
}
public CustomDateSerializer(Class<Date> t) {
super(t);
}
@Override
public void serialize(
Date value, JsonGenerator gen, SerializerProvider arg2)
throws IOException, JsonProcessingException {
gen.writeString(formatter.format(value));
}
}
測試:
@Test
public void whenSerializingUsingJsonSerialize_thenCorrect()
throws JsonProcessingException, ParseException {
SimpleDateFormat df
= new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
String toParse = "20-12-2014 02:30:00";
Date date = df.parse(toParse);
EventWithSerializer event = new EventWithSerializer("party", date);
String result = new ObjectMapper().writeValueAsString(event);
System.out.println(result);
}
不使用注解:
使用注解:
反序列化注解
@JsonCreator
我們可以使用 @JsonCreator 注釋來調整反序列化中使用的構造函數/工廠。
實體:
package com.yongren.jsonAnnotation;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
public class BeanWithCreator {
public int id;
public String name;
@JsonCreator
public BeanWithCreator(
@JsonProperty("id") int id,
@JsonProperty("theName") String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "BeanWithCreator{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
測試:
@Test
public void whenDeserializingUsingJsonCreator_thenCorrect()
throws IOException {
String json = "{\"id\":1,\"theName\":\"My bean\"}";
BeanWithCreator bean = new ObjectMapper()
.readerFor(BeanWithCreator.class)
.readValue(json);
System.out.println(bean);
}
使用注解,結果:
不使用注解,結果:
- 僅使用@JsonProperty,正常使用
- 不存在@JsonProperty,報錯
- 不使用任何注解,報錯
@JacksonInject
@JacksonInject表示屬性将從注入中擷取其值,而不是從 JSON 資料中擷取。根據類型推斷的,是以同一類型注入,隻能有一個;每個屬性注入都必須有值。
實體:
public class BeanWithInject {
@JacksonInject
public int id;
public String name;
@Override
public String toString() {
return "BeanWithInject{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
測試:
@Test
public void whenDeserializingUsingJsonInject_thenCorrect()
throws IOException {
String json = "{\"name\":\"My bean\"}";
InjectableValues inject = new InjectableValues.Std()
.addValue(int.class, 1);
BeanWithInject bean = new ObjectMapper().reader(inject)
.forType(BeanWithInject.class)
.readValue(json);
System.out.println(bean);
}
結果:
@JsonAnySetter
@JsonAnySetter允許我們靈活地使用Map作為标準屬性。在反序列化時,來自 JSON 的屬性将簡單地添加到映射中。
實體:
public class ExtendableBean {
public String name;
private Map<String, String> properties;
@JsonAnySetter
public void add(String key, String value) {
properties.put(key, value);
}
}
測試:
@Test
public void whenDeserializingUsingJsonAnySetter_thenCorrect()
throws IOException {
String json
= "{\"name\":\"My bean\",\"attr2\":\"val2\",\"attr1\":\"val1\"}";
ExtendableBean bean = new ObjectMapper()
.readerFor(ExtendableBean.class)
.readValue(json);
assertEquals("My bean", bean.name);
assertEquals("val2", bean.getProperties().get("attr2"));
}
測試結果:
使用注解:
不使用注解,将因屬性不比對爆錯。
@JsonSetter
@JsonSetter是@JsonProperty的替代方法,它将方法标記為 setter 方法。
當我們需要讀取一些 JSON 資料時,這非常有用,但目标實體類與該資料不完全比對,是以我們需要調整過程以使其适合。
@JsonGetter、@JsonSetter、@JsonProperty在各自作用範圍上使用,效果一樣。
@JsonDeserialize
@JsonDeserialize表示使用自定義反序列化器。
實體:
public class EventWithSerializer {
public String name;
@JsonDeserialize(using = CustomDateDeserializer.class)
public Date eventDate;
}
@JsonAlias
@JsonAlias定義反序列化過程為屬性的一個或多個的替代名稱。
實體:
package com.yongren.jsonAnnotation;
import com.fasterxml.jackson.annotation.JsonAlias;
public class AliasBean {
@JsonAlias({"fName", "f_name"})
private String firstName;
private String lastName;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
@Override
public String toString() {
return "AliasBean{" +
"firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
'}';
}
}
測試:
@Test
public void whenDeserializingUsingJsonAlias_thenCorrect() throws IOException {
String json = "{\"fName\": \"John\", \"lastName\": \"Green\"}";
AliasBean aliasBean = new ObjectMapper().readerFor(AliasBean.class).readValue(json);
String json2 = "{\"f_name\": \"John\", \"lastName\": \"Green\"}";
AliasBean aliasBean2 = new ObjectMapper().readerFor(AliasBean.class).readValue(json2);
System.out.println(aliasBean);
System.out.println(aliasBean2);
}
結果:
AliasBean{firstName='John', lastName='Green'}
AliasBean{firstName='John', lastName='Green'}
Jackson 屬性包含有關的注釋
@JsonIgnoreProperties
@JsonIgnoreProperties是一個類級别的注釋,用于标記 Jackson 将忽略的屬性或屬性清單。
實體:
@JsonIgnoreProperties({ "id" })
public class BeanWithIgnore {
public int id;
public String name;
}
測試:
@Test
public void whenSerializingUsingJsonIgnoreProperties_thenCorrect()
throws JsonProcessingException {
BeanWithIgnore bean = new BeanWithIgnore(1, "My bean");
String result = new ObjectMapper()
.writeValueAsString(bean);
System.out.println(result);
}
結果:
@JsonIgnore
JsonIgnore注解用于在字段級别标記要忽略的屬性。
@JsonIgnoreType
@JsonIgnoreType将注釋類型的所有屬性标記為被忽略。
例如:
public class User {
public int id;
public Name name;
@JsonIgnoreType
public static class Name {
public String firstName;
public String lastName;
}
}
@JsonInclude
我們可以使用@JsonInclude排除具有null/空/預設值的屬性。
實體:
@JsonInclude(Include.NON_NULL)
public class MyBean {
public int id;
public String name;
}
測試:
@Test
public void whenSerializingUsingJsonInclude_thenCorrect()
throws JsonProcessingException {
MyBean bean = new MyBean(1, null);
String result = new ObjectMapper()
.writeValueAsString(bean);
System.out.println(result);
}
結果:
@JsonAutoDetect
@JsonAutoDetect可以覆寫哪些屬性可見和哪些屬性不可見的預設語義。
實體:
package com.yongren.jsonAnnotation;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
@JsonAutoDetect(fieldVisibility = Visibility.PUBLIC_ONLY)
public class PrivateBean {
private int id;
private String name;
public PrivateBean() {
}
public PrivateBean(final int id, final String name) {
this.id = id;
this.name = name;
}
}
測試:
@Test
public void whenSerializingUsingJsonAutoDetect_thenCorrect()
throws JsonProcessingException {
PrivateBean bean = new PrivateBean(1, "My bean");
String result = new ObjectMapper()
.writeValueAsString(bean);
System.out.println(result);
}
結果:
Jackson 多态類型處理注解
接下來我們來看看Jackson多态類型處理注解:
- @JsonTypeInfo – 訓示序列化中包含哪些類型資訊的詳細資訊
- @JsonSubTypes – 表示注釋類型的子類型
- @JsonTypeName – 定義用于帶注釋的類的邏輯類型名稱
實體:
package com.yongren.jsonAnnotation;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeName;
public class Zoo {
public Animal animal;
public Zoo() {
}
@Override
public String toString() {
return "Zoo{" +
"animal=" + animal +
'}';
}
public Zoo(final Animal animal) {
this.animal = animal;
}
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY,property = "type")
@JsonSubTypes({ @JsonSubTypes.Type(value = Dog.class, name = "dog"), @JsonSubTypes.Type(value = Cat.class, name = "cat") })
public static class Animal {
public String name;
@Override
public String toString() {
return "Animal{" +
"name='" + name + '\'' +
'}';
}
public Animal() {
}
public Animal(final String name) {
this.name = name;
}
}
@JsonTypeName("dog")
public static class Dog extends Animal {
public double barkVolume;
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", barkVolume=" + barkVolume +
'}';
}
public Dog() {
}
public Dog(final String name) {
this.name = name;
}
}
@JsonTypeName("cat")
public static class Cat extends Animal {
boolean likesCream;
public int lives;
@Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
", likesCream=" + likesCream +
", lives=" + lives +
'}';
}
public Cat() {
}
public Cat(final String name) {
this.name = name;
}
}
}
測試:
@Test
public void whenSerializingPolymorphic_thenCorrect()
throws JsonProcessingException {
Zoo.Dog dog = new Zoo.Dog("lacy");
Zoo zoo = new Zoo(dog);
String result = new ObjectMapper()
.writeValueAsString(zoo);
System.out.println(result);
Zoo deserializeZoo = new ObjectMapper()
.readerFor(Zoo.class)
.readValue(result);
System.out.println(deserializeZoo);
}
結果:
{"animal":{"type":"dog","name":"lacy","barkVolume":0.0}}
Zoo{animal=Dog{name='lacy', barkVolume=0.0}}
Jackson 一般注釋
@JsonProperty
通過添加的@JsonProperty注釋,指明在JSON屬性名。
@JsonFormat
序列化日期/時間值時,用該@JsonFormat注解指定格式。
實體:
package com.yongren.jsonAnnotation;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.util.Date;
public class EventWithFormat {
public String name;
@JsonFormat(
shape = JsonFormat.Shape.STRING,
pattern = "yyyy-MM-dd hh:mm:ss")
public Date eventDate;
public EventWithFormat(String name, Date eventDate) {
this.name = name;
this.eventDate = eventDate;
}
}
測試:
@Test
public void whenSerializingUsingJsonFormat_thenCorrect()
throws JsonProcessingException, ParseException {
Date date=new Date();
System.out.println(date);
SimpleDateFormat df = new SimpleDateFormat("MM-dd-yyyy hh:mm:ss");
String format = df.format(date);
System.out.println(format);
date = df.parse(format);
EventWithFormat event = new EventWithFormat("party", date);
String result = new ObjectMapper().writeValueAsString(event);
System.out.println(result);
}
結果:
Thu Sep 16 10:46:53 CST 2021
09-16-2021 10:46:53
{"name":"party","eventDate":"2021-09-16 02:46:53"}
@JsonUnwrapped
@JsonUnwrapped定義了在序列化/反序列化時應該解包/展平的值。
實體:
package com.yongren.jsonAnnotation;
import com.fasterxml.jackson.annotation.JsonUnwrapped;
public class UnwrappedUser {
public int id;
@JsonUnwrapped
public Name name;
public UnwrappedUser(int id, Name name) {
this.id = id;
this.name = name;
}
public static class Name {
public String firstName;
public String lastName;
public Name(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
}
測試:
@Test
public void whenSerializingUsingJsonUnwrapped_thenCorrect()
throws JsonProcessingException, ParseException {
UnwrappedUser.Name name = new UnwrappedUser.Name("John", "Doe");
UnwrappedUser user = new UnwrappedUser(1, name);
String result = new ObjectMapper().writeValueAsString(user);
System.out.println(result);
}
結果:
@JsonView
@JsonView用于在序列化/反序列化時指定一個視圖類(視圖就是java類),僅有視圖對應的屬性被序列化/反序列化。
視圖:
public class Views {
}
class view1 {}
class view2 {}
class view3 {}
實體:
package com.yongren.jsonAnnotation;
import com.fasterxml.jackson.annotation.JsonView;
public class Item {
@JsonView(view1.class)
public int id;
@JsonView(view2.class)
public String itemName;
@JsonView(view3.class)
public String ownerName;
public Item(int id, String itemName, String ownerName) {
this.id = id;
this.itemName = itemName;
this.ownerName = ownerName;
}
}
結果:
{"id":2}
{"itemName":"book"}
三種方式處理JSON
- 流式API - -讀取并将JSON内容寫入作為離散事件。 JsonParser讀取資料,而JsonGenerator寫入資料。它是三者中最有效的方法,是最低的開銷和最快的讀/寫操作。它類似于Stax解析器XML。
- 樹模型 - - 準備JSON檔案在記憶體裡以樹形式表示。 ObjectMapper建構JsonNode節點樹。這是最靈活的方法。它類似于XML的DOM解析器。
- 資料綁定 – 轉換JSON并從POJO(普通Java對象)使用屬性通路或使用注釋。ObjectMapper讀/寫JSON兩種類型的資料綁定。資料綁定是最友善的方式是類似XML的JAXB解析器。它有兩個類型。
- 簡單的資料綁定 - -轉換JSON和Java Maps, Lists, Strings, Numbers, Booleans 和null 對象。
- 全部資料綁定 - -從任何JAVA類型轉換為JSON。
Jackson ObjectMapper
使用ObjectMapper類将 Java 對象序列化為 JSON 并将 JSON 字元串反序列化為 Java 對象。
使用ObjectMapper讀寫
- 使用
API将 JSON 内容解析或反序列化為 Java 對象。readValue
- 使用
writeValue
API 将任何 Java 對象序列化為 JSON 輸出。
示例實體:
package com.yongren.objectMapper;
public class Car {
private String color;
private String type;
public Car() {
}
public Car(String color, String type) {
this.color = color;
this.type = type;
}
// standard getters setters
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@Override
public String toString() {
return "Car{" +
"color='" + color + '\'' +
", type='" + type + '\'' +
'}';
}
}
Java 對象到 JSON
writeValue
使用ObjectMapper類的writeValue方法将 Java 對象序列化為 JSON 的示例:
@Test
public void usingWriteValue() {
ObjectMapper objectMapper = new ObjectMapper();
Car car = new Car("yellow", "renault");
try {
objectMapper.writeValue(new File("target/car.json"), car);
} catch (IOException e) {
e.printStackTrace();
}
}
檔案中的結果:
writeValueAsString
測試:
@Test
public void usingWriteValueAsString() {
ObjectMapper objectMapper = new ObjectMapper();
Car car = new Car("yellow", "renault");
try {
String carAsString = objectMapper.writeValueAsString(car);
System.out.println(carAsString);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
輸出:
writeValueAsBytes
測試:
@Test
public void usingWriteValueAsBytes() {
ObjectMapper objectMapper = new ObjectMapper();
Car car = new Car("yellow", "renault");
byte[] carAsString = null;
try {
carAsString = objectMapper.writeValueAsBytes(car);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
System.out.println(carAsString);
}
輸出:
JSON 到 Java 對象
readValue
測試:
@Test
public void usingReadValue() {
String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }";
try {
Car car = objectMapper.readValue(json, Car.class);
System.out.println(car);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
輸出:
readValue()函數還接受其他形式的輸入,諸如包含JSON字元串檔案:
或網址:
Car car =
objectMapper.readValue(new URL("file:src/test/resources/json_car.json"), Car.class);
JSON 到 Jackson JsonNode
可以将 JSON 解析為JsonNode對象并用于從特定節點檢索資料:
String json = "{ \"color\" : \"Black\", \"type\" : \"FIAT\" }";
JsonNode jsonNode = objectMapper.readTree(json);
String color = jsonNode.get("color").asText();
從 JSON 數組字元串建立 Java List
可以使用TypeReference将數組形式的 JSON 解析為 Java 對象清單:
String jsonCarArray =
"[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]";
List<Car> listCar = objectMapper.readValue(jsonCarArray, new TypeReference<List<Car>>(){});
輸出:
從 JSON 字元串建立 Java Map
可以使用TypeReference将數組形式的 JSON 解析為 Java Map:
String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }";
Map<String, Object> map
= objectMapper.readValue(json, new TypeReference<Map<String,Object>>(){});
輸出:
進階功能
配置序列化或反序列化功能
在将 JSON 對象轉換為 Java 類時,如果 JSON 字元串有一些新字段,預設過程将導緻異常:
示例:
String jsonString
= "{ \"color\" : \"Black\", \"type\" : \"Fiat\", \"year\" : \"1970\" }";
上例中的 JSON 字元串在預設解析為類 Car的 Java 對象的過程中将導緻
UnrecognizedPropertyException
異常。
通過
configure
方法,我們可以擴充預設流程來忽略新字段:
@Test
public void usingConfigure(){
String jsonString
= "{ \"color\" : \"Black\", \"type\" : \"Fiat\", \"year\" : \"1970\" }";
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
try {
Car car = objectMapper.readValue(jsonString, Car.class);
System.out.println(car);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
JsonNode jsonNodeRoot = null;
try {
jsonNodeRoot = objectMapper.readTree(jsonString);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
JsonNode jsonNodeYear = jsonNodeRoot.get("year");
String year = jsonNodeYear.asText();
System.out.println(year);
}
輸出:
Car{color='Black', type='Fiat'}
1970
另一個選項基于FAIL_ON_NULL_FOR_PRIMITIVES,它定義是否允許原始值的空值;
FAIL_ON_NUMBERS_FOR_ENUM控制是否允許将枚舉值序列化/反序列化為數字;
建立自定義序列化程式或反序列化程式
ObjectMapper類的另一個基本特性是能夠注冊自定義序列化器和反序列化器。
自定義序列化器和反序列化器在輸入或輸出 JSON 響應的結構與必須對其進行序列化或反序列化的 Java 類不同的情況下非常有用。
以下是自定義 JSON 序列化程式的示例:
public class CustomCarSerializer extends StdSerializer<Car> {
public CustomCarSerializer() {
this(null);
}
public CustomCarSerializer(Class<Car> t) {
super(t);
}
@Override
public void serialize(
Car car, JsonGenerator jsonGenerator, SerializerProvider serializer) {
jsonGenerator.writeStartObject();
jsonGenerator.writeStringField("car_brand", car.getType());
jsonGenerator.writeEndObject();
}
}
這個自定義序列化器可以這樣調用:
@Test
public void usingCustomCarSerializer(){
ObjectMapper mapper = new ObjectMapper();
SimpleModule module =
new SimpleModule("CustomCarSerializer", new Version(1, 0, 0, null, null, null));
module.addSerializer(Car.class, new CustomCarSerializer());
mapper.registerModule(module);
Car car = new Car("yellow", "renault");
try {
String carJson = mapper.writeValueAsString(car);
System.out.println(carJson);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
輸出:
處理日期格式
java.util.Date的預設序列化會産生一個數字,即紀元時間戳(自 1970 年 1 月 1 日起的毫秒數,UTC)。但這不是人類可讀的,需要進一步轉換才能以人類可讀的格式顯示。
實體:
public class Request
{
private Car car;
private Date datePurchased;
// standard getters setters
}
測試:
ObjectMapper objectMapper = new ObjectMapper();
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm a z");
objectMapper.setDateFormat(df);
String carAsString = objectMapper.writeValueAsString(request);
// output: {"car":{"color":"yellow","type":"renault"},"datePurchased":"2016-07-03 11:43 AM CEST"}