Jackson使用规范以及代码示例
依赖包
Maven依赖:
org.codehaus.jackson
jackson-mapper-asl
1.9.9
不同API规范以及示例
Data Binding API使用
Java对象转json
Java对象转json时对象私有属性必须具有属性的get/set方法,如果没有get方法将不能被序列化,并且get方法需要是默认的get方法,序列化后的json字符中的键值对中的键为Java对象的属性名,Java属性可以定义为共有和私有,如果Java对象属性为公有的话此属性可以没有get/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对象:
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转java对象
ObjectMapper mapper = new ObjectMapper();
User us = mapper.readValue(json, User.class);
System.out.println("反序列化后:"+us.getName()+us.getAdress()+us.getId());
Java对象转json过滤对象属性
使用注解@JsonIgnore过滤具体属性
对于一个Java对象,对其序列化时我们可以选择想要序列化的属性,对于不想序列化的属性,我们可以选择不进行序列化具体我们可以使用注解@JsonIgnore标注不需要序列化的属性的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过滤多个属性
如果需要同时有多个属性不需要序列化我们可以在类上进行注解指定多个属性不进行序列化,具体使用注解:@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过滤属性
我们也可以使用自定义FilterView并且使用其注解要序列化的属性,首先需要定义一个需要输出的属性的View:FilterView.Output,然后在需要输出属性上声明该View,之后使用writerWithView(FilterView.Output.class)来序列化就可以了。需要注意的是,在这里需要把DEFAULT_VIEW_INCLUSION设置为false,因为默认是会输出没有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));
}
}
其实View的作用远不止如此,再来看一个更实用的例子:假设现有个API接口,需要针对不同的客户端(ios,android)输出不同的属性,通过创建多个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);
}
}
不修改源码通过自定义类过滤属性
在不需要修改源码的情况下我们可以使用另外一种方式进行属性序列化的过滤,我们可以定义一个类MixIn来设置属性过滤条件,具体使用如下:
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结合实现动态过滤
对于使用MixIn只能实现静态过滤,我们可以使用json filter与MixIn结合实现动态过滤,可以动态指定需要序列化的属性,具体使用示例如下:
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对象转json
对于一些嵌套对象进行序列化为json,比如User的其中一个属性Adress为一个Java对象,Adress拥有一些属性,则对这种嵌套对象序列化时需要注意Adress对象也要拥有get/set方法,否则不能进行序列化,序列化示例如下:
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对象的属性中含有ArrayList或是HashMap的情况下也可以进行序列化,具体使用使用示例如下:
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转嵌套Java对象
Json可以直接转为嵌套Java对象,具体使用示例如下:
ObjectMapper mapper = new ObjectMapper();
User us = mapper.readValue(json, User.class);
System.out.println("反序列化后:"+us.getName()+""+us.getAdress().getPostnum()+""+us.getId());
Json转为带有ArrayList或是HashMap的Java对象同样可以反序列化,具体使用示例如下:
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转json
Map转json是map的value可以指定类型也可以直接定义为object,注意:如果在map中放入自定义对象比如User是将User序列化为字符串,在反序列化的时候不能讲设置的user对象反序列化。
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转map
在上面map转json时如果将map的value设置为object时在设置value时任意指定value类型的情况下将json转map时可以将value指定类型。
Map map = new HashMap();
ObjectMapper mapper = new ObjectMapper();
map = mapper.readValue(json, HashMap.class);
System.out.println("反序列化后:" + map);
List转json
ArrayList转json时list中的add的对象可以指定具体类型也可以直接设置为Object,都可以进行序列化,注意:如果在list中放入自定义对象比如User是将User序列化为字符串,在反序列化的时候不能讲设置的user对象反序列化。
ArrayList list = new ArrayList();
list.add("张小明");
list.add(27);
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(list);
System.out.println("序列化后:" + json);
Json转list
在将Arraylist序列化为json时list中的对象设置为不同类型的情况下将json反序列化是可以将List中的对象类型设置为指定类型,比如设置为String。
ArrayList list = new ArrayList();
ObjectMapper mapper = new ObjectMapper();
list = mapper.readValue(json, ArrayList.class);
System.out.println("反序列化后:" + list);
Map、List中有Java对象转为json
Map、list中可以添加普通String对象以及自定义的Java对象,序列化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转为内有Java对象的Map、List
当json是有负责的map对象序列化的情况下,比如map中有普通String对象和自定义Java对象的情况下需要将json反序列化,此时需要设置反序列化后的类型为: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数组转json
数组序列化为json,比如字符数组或是int数组序列化为json时具体使用示例如下:
int[] num = new int[]{1,5};
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(num);
System.out.println("序列化后:" + json);
Json转array
在将json反序列为数组时,定义数组大小可以不等于序列化为json之前的数组大小,具体使用示例如下:
int[] num = new int[3];
ObjectMapper mapper = new ObjectMapper();
num = mapper.readValue(json, int[].class);
System.out.println("反序列化后:" + num[1]);
使用Tree Model API进行反序列化
接下来看一下反序列化,现在很多网站都开放了api接口,支持json格式的返回。比如在调用了某个api后,需要解析返回的json数据获取信息,这种情况下为json创建一个对应的类是很不方便的。此时使用Tree Model来解析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。
具体文本内容示例:
{
"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生产json格式内容到文件或OutputStream
如果我们希望创建json格式的内容并且将其写入文件或是字节流的话可以使用Streaming API轻松创建json格式的内容并将其写到文件或是字节流、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的最佳实践:
[if !supportLists]·[endif]重用重量级对象: ObjectMapper, JsonFactory
[if !supportLists]·[endif]序列化性能(从高到低):OutputStream > Writer > writeValueAsString
[if !supportLists]·[endif]反序列化性能(从高到低):byte[] > InputStream > Reader
[if !supportLists]·[endif]用更轻量ObjectReader/ObjectWriter替代ObjectMapper
[if !supportLists]·[endif]及时关闭JsonParser, JsonGenerator
本文是自己研究jackson使用时整理的,有些内容是网上查询的!