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>
<!--數(shù)據(jù)綁定-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.6</version>
</dependency>
Jackson的基本應(yīng)用:
JsonNode 類是 Jackson 的一個將 Json
內(nèi)容反序列到內(nèi)存的一種內(nèi)存數(shù)據(jù)結(jié)構(gòu)表達(dá)方式放祟。
例如對于一個測試的Json內(nèi)容:
{
"name" : "test",
"value" : 20,
"address" : [
{
"addressId" : "0001"
},
{
"addressId" : "0002"
}
]
}
當(dāng)我們把json內(nèi)容反序列化到內(nèi)存中的時(shí)候,便可以如同操作一個樹結(jié)構(gòu)讀取json內(nèi)容:
String name = node.get("name").asText();
Integer value = node.get("value").asInt();
Iterator<JsonNode> addressNodes = node.get("address").elements();
String address = addressNodes.next().get("addressId").asText();
從上我們可以發(fā)現(xiàn)跪妥, jackson 可以方便的進(jìn)行節(jié)點(diǎn)定位跟類型轉(zhuǎn)換。
如何才能將json內(nèi)容轉(zhuǎn)換成 JsonNode 呢 眉撵?
- 文件字符串解析
public static JsonNode str2JsonNode(String str) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readTree(str);
}
- stream 解析
public static JsonNode str2JsonNode(InputStream stream) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readTree(stream);
}
- file 解析
public static JsonNode str2JsonNode(File file) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readTree(file);
}
- reader 解析
public static JsonNode str2JsonNode(Reader reader) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readTree(reader);
}
- bytes 解析
public static JsonNode str2JsonNode(byte[] datas) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readTree(datas);
}
Json 與 基本類型的相互轉(zhuǎn)化:
readValue 方法能夠幫助我們將字符串序列化成指定的
public static Object json2Object(String str) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
JsonNode node = objectMapper.readTree(str);
if(node.isObject()){
return objectMapper.readValue(str, Map.class);
}else if(node.isArray()){
return objectMapper.readValue(str, List.class);
}else{
if (node.isInt()) {
return node.asInt();
} else if (node.isLong()) {
return node.asLong();
} else if (node.isDouble()) {
return node.asDouble();
} else if(node.isTextual()) {
return node.asText();
} else if (node.isNull()){
return null;
}
else {
throw new IOException("Json node exception type : " + node.numberType());
}
}
}
例如上面的字符串我們將其解析為 常見的Map結(jié)構(gòu):
Map map = JsonUtil.json2Bean(str, Map.class);
System.out.println(map.get("address"));
List<Map<String, String>> list = (List<Map<String, String>>)map.get("address");
System.out.println(list.get(1).get("addressId"));
當(dāng)然我們也可以通過 writeValue的方式將普通類型轉(zhuǎn)換成 String 打印出來:
public static String object2Str(Object object, boolean prettyPrint) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
// 美化方式打印
if(prettyPrint){
ObjectWriter write = objectMapper.writerWithDefaultPrettyPrinter();
return write.writeValueAsString(object);
}
// 單行打印
return objectMapper.writeValueAsString(object);
}
String 與 Bean 的相互轉(zhuǎn)化
- 轉(zhuǎn)換工具方法為:
public static <T> T str2Bean(String str, Class<T> beanClass) throws IOException {
ObjectMapper mapper = new ObjectMapper();
return mapper.readValue(str, beanClass);
}
要將 string -> bean , 對于每一個 jsonStr, 我們都需要創(chuàng)建一個與之對應(yīng)的 bean class.
例如 :
{
"name" : "test",
"value" : 20
}
對應(yīng)的 Bean 為 :
public class Persion {
private String name;
private int value;
public void setName(String name) {
this.name = name;
}
public void setValue(int value) {
this.value = value;
}
}
我們通過 Persion persion = JsonUtil.str2Bean(str, Persion.class);
這時(shí)候會通過 setter
方法將json內(nèi)容注入到 Persion
類的對應(yīng)字段中。
如果 json 中的 key 與 Bean 中的字段名稱不對應(yīng)芜赌,我們可以通過 @JsonProperty 注解為其聲明對應(yīng)關(guān)系仰挣。
@JsonProperty 注解可以用于 getter
,setter
,或者構(gòu)造函數(shù)參數(shù)中。
例如 :
public class Persion {
private String name;
private int value;
@JsonProperty("v-name")
public void setName(String name) {
this.name = name;
}
@JsonProperty("v-value")
public void setValue(int value) {
this.value = value;
}
}
- 排除未知的字段@JsonIgnoreProperties(ignoreUnknown = true)
有時(shí)候json中出了具有bean聲明的字段以外膘壶,有時(shí)候還會有其他信息,但這些信息并不是我們所關(guān)系的颓芭,我們這時(shí)候就需要舍棄這部分內(nèi)容, 我們可以在類開始處使用 @JsonIgnoreProperties(ignoreUnknown = true) 注解亡问,忽略掉不匹配或者轉(zhuǎn)換失敗的字段。
@JsonIgnoreProperties(ignoreUnknown = true)
public class Persion {
private String name;
private int value;
@JsonProperty("v-name")
public void setName(String name) {
this.name = name;
}
@JsonProperty("v-value")
public void setValue(int value) {
this.value = value;
}
}
- 自定義序列號與反序列化方式:
有時(shí)候 json 與 bean 并不是簡單的對應(yīng)關(guān)系州藕, 反序列化過程往往存在困難, 例如對于開始處這個 json 內(nèi)容 :
{
"name" : "test",
"value" : 20,
"address" : [
{
"addressId" : "0001"
},
{
"addressId" : "0002"
}
]
}
我們的對應(yīng) bean 為:
public class Persion {
private String name;
private int value;
private List<Address> address;
}
public class Address {
private String addressId;
public void setAddressId(String addressId) {
this.addressId = addressId;
}
}
正常情況下床玻, 對于 address 字段會映射為 List<Map>
類型, 但是此處我們需要讓他自動轉(zhuǎn)換為 List<Address>
這時(shí)候就需要我們自定義反序列化過程:
反序列化類需要繼承 JsonDeserializer<T>
泛型對應(yīng)反序列化的返回類型 :
反序列化工具類
public class AddressDeserde extends JsonDeserializer<List> {
public List deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
JsonNode nodes = mapper.readTree(jsonParser);
List<Address> addresses = new LinkedList<Address>();
for(JsonNode node : Lists.newArrayList(nodes.elements())){
System.out.println(node.toString());
addresses.add(JsonUtil.str2Bean(node.toString(), Address.class));
}
return addresses;
}
}
然后便可以再 bean 中字段指名反序列化工具:
@JsonIgnoreProperties(ignoreUnknown = true)
public class Persion {
private String name;
private int value;
private List<Address> address;
@JsonProperty("v-name")
public void setName(String name) {
this.name = name;
}
@JsonProperty("v-value")
public void setValue(int value) {
this.value = value;
}
@JsonProperty("address")
@JsonDeserialize(using = bean.AddressDeserde.class)
public void setAddress(List<Address> address) {
this.address = address;
}
@Override
public String toString() {
return "Persion{" +
"name='" + name + '\'' +
", value=" + value +
", addresses=" + address +
'}';
}
}
這時(shí)候便可以用了。
同樣的锈死,我們要自定義序列化方式需要繼承 JsonSerializer<T>
抽象方法
例如對于 address
的字段,的序列化過程:
public class AddressSerde extends JsonSerializer<List<Address>> {
@Override
public void serialize(List<Address> addresses, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeStartArray();
for(Address address : addresses){
jsonGenerator.writeObject(address);
}
jsonGenerator.writeEndArray();
}
}
我們可以在 getter
方法中加入序列化方式:
@JsonProperty("v-address")
@JsonSerialize(using = bean.AddressSerde.class)
public List<Address> getAddress() {
return address;
}
然后便能夠成功的解析出 List<Address>