Jackson使用規(guī)范以及代碼示例
依賴包
Maven依賴:
org.codehaus.jackson
jackson-mapper-asl
1.9.9
不同API規(guī)范以及示例
Data Binding API使用
Java對(duì)象轉(zhuǎn)json
Java對(duì)象轉(zhuǎn)json時(shí)對(duì)象私有屬性必須具有屬性的get/set方法,如果沒(méi)有g(shù)et方法將不能被序列化,并且get方法需要是默認(rèn)的get方法持偏,序列化后的json字符中的鍵值對(duì)中的鍵為Java對(duì)象的屬性名饺窿,Java屬性可以定義為共有和私有,如果Java對(duì)象屬性為公有的話此屬性可以沒(méi)有g(shù)et/set方法具體使用示例如下:
User? user = new User();
user.setAdress("南京市");
user.setId(27);
user.setName("張小明");
ObjectMapper? mapper = new ObjectMapper();
String? json = mapper.writeValueAsString(user);
System.out.println("序列化后:" + json);
User對(duì)象:
class User {
private? String name;
private? int id;
private? String adress;
public? void setName(String name) {
this.name? = name;
}
public? void setId(int id) {
this.id? = id;
}
public? void setAdress(String adress) {
this.adress? = adress;
}
public? String getName() {
return? name;
}
public? int getId() {
return? id;
}
public? String getAdress() {
return? adress;
}
}
Json轉(zhuǎn)java對(duì)象
ObjectMapper? mapper = new ObjectMapper();
User? us = mapper.readValue(json, User.class);
System.out.println("反序列化后:"+us.getName()+us.getAdress()+us.getId());
Java對(duì)象轉(zhuǎn)json過(guò)濾對(duì)象屬性
使用注解@JsonIgnore過(guò)濾具體屬性
對(duì)于一個(gè)Java對(duì)象绘梦,對(duì)其序列化時(shí)我們可以選擇想要序列化的屬性寝衫,對(duì)于不想序列化的屬性稀拐,我們可以選擇不進(jìn)行序列化具體我們可以使用注解@JsonIgnore標(biāo)注不需要序列化的屬性的get方法握截,具體使用如下:比如不想序列化User的name
class User {
private? String name;
private? int id;
private? Adress adress;
public? void setName(String name) {
this.name? = name;
}
public? void setId(int id) {
this.id? = id;
}
@JsonIgnore
public? String getName() {
return? name;
}
public? int getId() {
return? id;
}
public? Adress getAdress() {
return? adress;
}
public? void setAdress(Adress adress) {
this.adress? = adress;
}
}
使用注解@JsonIgnoreProperties過(guò)濾多個(gè)屬性
如果需要同時(shí)有多個(gè)屬性不需要序列化我們可以在類上進(jìn)行注解指定多個(gè)屬性不進(jìn)行序列化,具體使用注解:@JsonIgnoreProperties({"id","name"})烂叔,具體示例代碼如下:
@JsonIgnoreProperties({"id","name"})
class User {
private? String name;
private? int id;
private? Adress adress;
public? void setName(String name) {
this.name? = name;
}
public? void setId(int id) {
this.id? = id;
}
public? String getName() {
return? name;
}
public? int getId() {
return? id;
}
public? Adress getAdress() {
return? adress;
}
public? void setAdress(Adress adress) {
this.adress? = adress;
}
}
使用FilterView過(guò)濾屬性
我們也可以使用自定義FilterView并且使用其注解要序列化的屬性谨胞,首先需要定義一個(gè)需要輸出的屬性的View:FilterView.Output,然后在需要輸出屬性上聲明該View蒜鸡,之后使用writerWithView(FilterView.Output.class)來(lái)序列化就可以了胯努。需要注意的是牢裳,在這里需要把DEFAULT_VIEW_INCLUSION設(shè)置為false,因?yàn)槟J(rèn)是會(huì)輸出沒(méi)有JsonView注解的屬性的叶沛。
public class JsonViewDemo {
private? static class User {
private? long id;
@JsonView({? FilterView.Output.class })
private? String name;
@JsonView({? FilterView.Output.class })
private? String address;
public? long getId() {
return? id;
}
public? String getName() {
return? name;
}
public? String getAddress() {
return? address;
}
}
private? static class FilterView {
static? class Output {
}
}
public? static void main(String[] args) throws Exception {
User? user = new User();
user.id? = 1000L;
user.name? = "張小明";
user.address? = "南京市";
ObjectMapper? mapper = new ObjectMapper();
mapper.configure(SerializationConfig.Feature.DEFAULT_VIEW_INCLUSION,false);
System.out.println(mapper.writerWithView(FilterView.Output.class).writeValueAsString(user));
}
}
其實(shí)View的作用遠(yuǎn)不止如此蒲讯,再來(lái)看一個(gè)更實(shí)用的例子:假設(shè)現(xiàn)有個(gè)API接口,需要針對(duì)不同的客戶端(ios,android)輸出不同的屬性灰署,通過(guò)創(chuàng)建多個(gè)View就能輕松完成判帮,具體使用示例如下:
public? class JsonApiViewDemo {
private? static class User {
private? long id;
@JsonView({ApiView.Default.class})
private? String name;
@JsonView({ApiView.Ios.class})
private? String avator240;
@JsonView({ApiView.Android.class})
private? String avator160;
private? String address;
public? long getId() {
return? id;
}
public? String getName() {
return? name;
}
public? String getAddress() {
return? address;
}
public? String getAvator240() {
return? avator240;
}
public? String getAvator160() {
return? avator160;
}
}
private? static class ApiView {
static? class Default {}
static? class Ios extends Default {}
static? class Android extends Default {}
}
public? static void main(String[] args) throws Exception {
ObjectMapper? mapper = new ObjectMapper();
mapper.configure(SerializationConfig.Feature.DEFAULT_VIEW_INCLUSION,? false);
User? user = new User();
user.id? = 10000L;
user.name
= "張小明";
user.avator240? = "240.jpg";
user.avator160? = "160.jpg";
user.address
= "南京市";
String? apiViewJson =? mapper.writerWithView(ApiView.Default.class).writeValueAsString(user);
String? iosViewJson = mapper.writerWithView(ApiView.Ios.class).writeValueAsString(user);
String? androidViewJson =? mapper.writerWithView(ApiView.Android.class).writeValueAsString(user);
System.out.println(apiViewJson);
System.out.println(iosViewJson);
System.out.println(androidViewJson);
}
}
不修改源碼通過(guò)自定義類過(guò)濾屬性
在不需要修改源碼的情況下我們可以使用另外一種方式進(jìn)行屬性序列化的過(guò)濾,我們可以定義一個(gè)類MixIn來(lái)設(shè)置屬性過(guò)濾條件溉箕,具體使用如下:
public class JsonMixInDemo {
static? class User {
private long id;
private String name;
private String avator240;
private String avator160;
private String address;
public long getId() {
return id;
}
public String getName() {
return name;
}
public String getAddress() {
return address;
}
}
abstract class MixIn {
@JsonIgnore abstract int getAddress();
@JsonIgnore long id;
@JsonProperty("custom_name") abstract String getName();
@JsonProperty("avator") String avator240;
}
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
User user = new User();
user.id = 1234567L;
user.name = "張小明";
user.avator240 = "240.jpg";
user.avator160 = "160.jpg";
user.address = "南京市";
mapper.getSerializationConfig().addMixInAnnotations(User.class,? MixIn.class);
String json = mapper.writeValueAsString(user);
System.out.println(json);
}
}
JSON Filter與MixIn結(jié)合實(shí)現(xiàn)動(dòng)態(tài)過(guò)濾
對(duì)于使用MixIn只能實(shí)現(xiàn)靜態(tài)過(guò)濾晦墙,我們可以使用json filter與MixIn結(jié)合實(shí)現(xiàn)動(dòng)態(tài)過(guò)濾,可以動(dòng)態(tài)指定需要序列化的屬性肴茄,具體使用示例如下:
public class JsonFilterDemo {
private? static class User {
private long id;
private String name;
private String avator240;
private String avator160;
private String address;
public String getName() {
return name;
}
public String getAddress() {
return address;
}
public String getAvator240() {
return avator240;
}
public String getAvator160() {
return avator160;
}
public long getId() {
return id;
}
}
@JsonFilter("userFilter")
private static interface UserFilterMixIn
{
}
public? static void main(String[] args) throws Exception {
ObjectMapper? mapper = new ObjectMapper();
User? user = new User();
user.id? = 1000L;
user.name? = "張小明";
user.avator240? = "240.jpg";
user.avator160? = "160.jpg";
user.address? = "南京市";
FilterProvider? idFilterProvider = new? SimpleFilterProvider().addFilter("userFilter",
SimpleBeanPropertyFilter.filterOutAllExcept(new? String[] {"name", "avator240" ,"address"}));
mapper.setFilters(idFilterProvider);
mapper.getSerializationConfig().addMixInAnnotations(User.class,
UserFilterMixIn.class);
String? userFilterJson = mapper.writeValueAsString(user);
System.out.println(userFilterJson);
}
}
嵌套Java對(duì)象轉(zhuǎn)json
對(duì)于一些嵌套對(duì)象進(jìn)行序列化為json晌畅,比如User的其中一個(gè)屬性Adress為一個(gè)Java對(duì)象,Adress擁有一些屬性寡痰,則對(duì)這種嵌套對(duì)象序列化時(shí)需要注意Adress對(duì)象也要擁有g(shù)et/set方法抗楔,否則不能進(jìn)行序列化,序列化示例如下:
User? user = new User();
Adress? adress = new Adress();
adress.setPostnum(464435);
adress.setSheng("江蘇省");
adress.setXian("江寧");
user.setAdress(adress);
user.setId(27);
user.setName("張小明");
ObjectMapper? mapper = new ObjectMapper();
String? json = mapper.writeValueAsString(user);
System.out.println("序列化后:" + json);
同樣拦坠,Java對(duì)象的屬性中含有ArrayList或是HashMap的情況下也可以進(jìn)行序列化连躏,具體使用使用示例如下:
User? user = new User();
user.setId(27);
user.setName("張小明");
//user.setAdress("南京市");
Adress? adress = new Adress();
adress.setPostnum(464435);
adress.setSheng("江蘇省");
adress.setXian("江寧");
user.setAdress(adress);
ArrayList? phoneList = new ArrayList();
phoneList.add("156333568956");
phoneList.add("10086");
user.setList(phoneList);
HashMap? map = new HashMap();
map.put("phone",? "10086");
user.setMap(map);
ObjectMapper? mapper = new ObjectMapper();
String? json = mapper.writeValueAsString(user);
System.out.println("序列化后:" + json);
Json轉(zhuǎn)嵌套Java對(duì)象
Json可以直接轉(zhuǎn)為嵌套Java對(duì)象,具體使用示例如下:
ObjectMapper? mapper = new ObjectMapper();
User? us = mapper.readValue(json, User.class);
System.out.println("反序列化后:"+us.getName()+""+us.getAdress().getPostnum()+""+us.getId());
Json轉(zhuǎn)為帶有ArrayList或是HashMap的Java對(duì)象同樣可以反序列化贪婉,具體使用示例如下:
ObjectMapper? mapper = new ObjectMapper();
User? us = mapper.readValue(json, User.class);
System.out.println("反序列化后:"+us.getName()+""+us.getAdress().getPostnum()+""+us.getId()+""+us.getList()+""+us.getMap().get("phone"));
Map轉(zhuǎn)json
Map轉(zhuǎn)json是map的value可以指定類型也可以直接定義為object反粥,注意:如果在map中放入自定義對(duì)象比如User是將User序列化為字符串,在反序列化的時(shí)候不能講設(shè)置的user對(duì)象反序列化疲迂。
Map map = new HashMap();
map.put("name",
"張小明");
map.put("id",? 27);
map.put("address",
"南京市");
ObjectMapper? mapper = new ObjectMapper();
String? json = mapper.writeValueAsString(map);
System.out.println("序列化后:" + json);
Json轉(zhuǎn)map
在上面map轉(zhuǎn)json時(shí)如果將map的value設(shè)置為object時(shí)在設(shè)置value時(shí)任意指定value類型的情況下將json轉(zhuǎn)map時(shí)可以將value指定類型才顿。
Map map = new HashMap();
ObjectMapper? mapper = new ObjectMapper();
map =? mapper.readValue(json, HashMap.class);
System.out.println("反序列化后:" + map);
List轉(zhuǎn)json
ArrayList轉(zhuǎn)json時(shí)list中的add的對(duì)象可以指定具體類型也可以直接設(shè)置為Object,都可以進(jìn)行序列化尤蒿,注意:如果在list中放入自定義對(duì)象比如User是將User序列化為字符串郑气,在反序列化的時(shí)候不能講設(shè)置的user對(duì)象反序列化。
ArrayList? list = new ArrayList();
list.add("張小明");
list.add(27);
ObjectMapper? mapper = new ObjectMapper();
String? json = mapper.writeValueAsString(list);
System.out.println("序列化后:" + json);
Json轉(zhuǎn)list
在將Arraylist序列化為json時(shí)list中的對(duì)象設(shè)置為不同類型的情況下將json反序列化是可以將List中的對(duì)象類型設(shè)置為指定類型腰池,比如設(shè)置為String尾组。
ArrayList? list = new ArrayList();
ObjectMapper? mapper = new ObjectMapper();
list =? mapper.readValue(json, ArrayList.class);
System.out.println("反序列化后:" + list);
Map、List中有Java對(duì)象轉(zhuǎn)為json
Map示弓、list中可以添加普通String對(duì)象以及自定義的Java對(duì)象讳侨,序列化json的使用示例如下:
User? user = new User();
user.setId(27);
user.setName("張小明");
ArrayList? list = new ArrayList();
list.add("張小明");
list.add(27);
list.add(user);
ObjectMapper? mapper = new ObjectMapper();
String? json = mapper.writeValueAsString(list);
System.out.println("序列化后:" + json);
Json轉(zhuǎn)為內(nèi)有Java對(duì)象的Map、List
當(dāng)json是有負(fù)責(zé)的map對(duì)象序列化的情況下奏属,比如map中有普通String對(duì)象和自定義Java對(duì)象的情況下需要將json反序列化跨跨,此時(shí)需要設(shè)置反序列化后的類型為:ArrayList>,具體使用示例如下:
ObjectMapper? mapper = new ObjectMapper();
User? user = new User();
ArrayList> list = mapper.readValue(json, ArrayList.class);
user.setName(list.get(2).get("name").toString());
Array數(shù)組轉(zhuǎn)json
數(shù)組序列化為json,比如字符數(shù)組或是int數(shù)組序列化為json時(shí)具體使用示例如下:
int[]? num = new int[]{1,5};
ObjectMapper? mapper = new ObjectMapper();
String? json = mapper.writeValueAsString(num);
System.out.println("序列化后:" + json);
Json轉(zhuǎn)array
在將json反序列為數(shù)組時(shí)勇婴,定義數(shù)組大小可以不等于序列化為json之前的數(shù)組大小忱嘹,具體使用示例如下:
int[]? num = new int[3];
ObjectMapper? mapper = new ObjectMapper();
num =? mapper.readValue(json, int[].class);
System.out.println("反序列化后:" + num[1]);
使用Tree Model API進(jìn)行反序列化
接下來(lái)看一下反序列化,現(xiàn)在很多網(wǎng)站都開(kāi)放了api接口耕渴,支持json格式的返回拘悦。比如在調(diào)用了某個(gè)api后,需要解析返回的json數(shù)據(jù)獲取信息橱脸,這種情況下為json創(chuàng)建一個(gè)對(duì)應(yīng)的類是很不方便的础米。此時(shí)使用Tree Model來(lái)解析json就比較方便了。
ObjectMapper mapper = new? ObjectMapper();
File file = new? File("c:/test.txt");
JsonNode rootNode = mapper.readValue(file,? JsonNode.class);
String name =? rootNode.get("name").getTextValue();
String adress =? rootNode.get("adress").getTextValue();
System.out.println(name+""+adress);
可以解析文件或是URL或是InputStream慰技。
具體文本內(nèi)容示例:
{
"name" : "張小明",
"adress" : "南京市"
}
也可以使用另外一種方式椭盏,具體代碼示例如下:
File file = new? File("c:/test.txt");
JsonParser jp =? mapper.getJsonFactory().createJsonParser(file);
JsonNode rootNode =? mapper.readTree(jp);
String name =? rootNode.get("name").getTextValue();
String adress = rootNode.get("adress").getTextValue();
System.out.println(name+""+adress);
使用Streaming API生產(chǎn)json格式內(nèi)容到文件或OutputStream
如果我們希望創(chuàng)建json格式的內(nèi)容并且將其寫入文件或是字節(jié)流的話可以使用Streaming API輕松創(chuàng)建json格式的內(nèi)容并將其寫到文件或是字節(jié)流、URL中吻商。具體使用示例如下:
JsonFactory? f = new JsonFactory();
JsonGenerator? g = null;
//OutputStream out =? null;
//g =? f.createJsonGenerator(out, JsonEncoding.UTF8);
g =? f.createJsonGenerator(new File("c:/user.json"), JsonEncoding.UTF8);
g.writeStartObject();
g.writeObjectFieldStart("name");
g.writeStringField("first",? "Joe");
g.writeStringField("last",? "Sixpack");
g.writeEndObject();
g.writeStringField("gender",? "MALE");
g.writeBooleanField("verified",? false);
g.writeFieldName("userImage");
byte[]? binaryData = new byte[]{22,33,44};
g.writeBinary(binaryData);
g.writeEndObject();
g.close();
最后列一些使用Jackson的最佳實(shí)踐:
[if !supportLists]·[endif]重用重量級(jí)對(duì)象: ObjectMapper, JsonFactory
[if !supportLists]·[endif]序列化性能(從高到低):OutputStream > Writer > writeValueAsString
[if !supportLists]·[endif]反序列化性能(從高到低):byte[] > InputStream > Reader
[if !supportLists]·[endif]用更輕量ObjectReader/ObjectWriter替代ObjectMapper
[if !supportLists]·[endif]及時(shí)關(guān)閉JsonParser, JsonGenerator
本文是自己研究jackson使用時(shí)整理的掏颊,有些內(nèi)容是網(wǎng)上查詢的!