Jackson使用指南

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使用时整理的,有些内容是网上查询的!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,158评论 4 370
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,600评论 1 307
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 111,785评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,655评论 0 220
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,075评论 3 295
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,002评论 1 225
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,146评论 2 318
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,918评论 0 211
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,671评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,838评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,318评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,636评论 3 263
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,343评论 3 244
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,187评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,982评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,126评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,934评论 2 279

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,111评论 18 139
  • 1.概述2.Gson的目标3.Gson的性能和扩展性4.Gson的使用者5.如何使用Gson 通过Maven来使用...
    人失格阅读 14,079评论 2 18
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,300评论 18 399
  • 昨天有朋友让我帮忙给她的公众号画配图。她是做职业顾问的,因为在外企工作过,有一些人脉。现在多数是给外企做相关的HR...
    温迪画画阅读 784评论 13 8