0%

Jackson初体验

WX20200925-185945@2x.png

Jsckson

主要模块

Streaming : jackson-core jar,定义了底层的streaming API和实现了Json特性。
Annotations: jackson-annotations jar,包含了标准的Jackson注解。
Databind : jackson-databind jar,实现了数据绑定和对象序列化,它依赖于streaming和annotations的包。

快速入门

Object -> Json

writevalue(….)

1
2
3
4
5
6
7
8
ObjectMapper mapper = new ObjectMapper();
Staff obj = new Staff();

// Object to JSON in file
mapper.writeValue(new File("c:\\file.json"), obj);

// Object to JSON in String
String jsonInString = mapper.writeValueAsString(obj);

Json -> object

1
2
3
4
5
6
7
8
9
10
11
ObjectMapper mapper = new ObjectMapper();
String jsonInString = "{'name' : 'mjw'}";

// JSON from file to Object
Staff obj = mapper.readValue(new File("c:\\file.json"), Staff.class);

// JSON from URL to Object
Staff obj = mapper.readValue(new URL("http://www.jianshu.com/u/c38e94dcec65"), Staff.class);

// JSON from String to Object
Staff obj = mapper.readValue(jsonInString, Staff.class);

Pojo

1
2
3
4
5
public class ExampleListener implements MessageListener {
public void onMessage(Message message){

}
}

Java 和 JSON 的相互转换

下面通过一个实例,说明如何使用 Jackson 实现JSON和Java对象相互转换。
Album 类,包含一个字段:

1
2
3
4
5
6
7
8
9
class Album {
private String title;
public Album(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
}

使用 ObjectMapper 进行转换

Jackson 默认使用 BeanSerializer 序列化POJO,要求对应的字段为 public,或者有对应的 getter 方法。

输出:

{“title”:”Kind Of Blue”}

数组序列化

现在继续向 Album 添加一个数组字段及对应的 getter 和 setter 方法:

1
2
3
4
5
6
7
private String[] links;
public String[] getLinks(){
return links;
}
public void setLinks(String[] links){
this.links = links;
}
1
2
3
4
Album album = new Album("Kind Of Blue");
album.setLinks(new String[]{"link1", "link2"});
ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(System.out, album);

输出:

{“title”:”Kind Of Blue”,”links”:[“link1”,”link2”]}

List 序列化

1
2
3
4
5
6
7
private List<String> songs;
public List<String> getSongs(){
return songs;
}
public void setSongs(List<String> songs){
this.songs = songs;
}
1
2
3
4
5
6
7
8
9
10
11
12
Album album = new Album("Kind Of Blue");
album.setLinks(new String[]{"link1", "link2"});

List<String> songs = new ArrayList<>();
songs.add("So what");
songs.add("Flamenco Sketches");
songs.add("Freddie Freeloader");

album.setSongs(songs);

ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(System.out, album);

输出:

{“title”:”Kind Of Blue”,”links”:[“link1”,”link2”],”songs”:[“So what”,”Flamenco Sketches”,”Freddie Freeloader”]}

从输出结构可以看到,List和数组的输出格式是一样的。

Java 对象序列化

Java 对象,序列化后在JSON中被 {} 括起来。
定义Artist 类:

1
2
3
4
public class Artist{
public String name;
public Date birthDate;
}

在Album 中添加对应的字段,并在 main 中设置其值:

1
2
3
4
5
Artist artist = new Artist();
artist.name = "Miles Davis";
SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");
artist.birthDate = format.parse("26-05-1926");
album.setArtist(artist);

格式化输出

配置 ObjectMapper ,可以让输出更好看一些:

1
mapper.configure(SerializationFeature.INDENT_OUTPUT, true);

此时的JSON输出如下:

1
2
3
4
5
6
7
8
9
{
"title" : "Kind Of Blue",
"links" : [ "link1", "link2" ],
"songs" : [ "So what", "Flamenco Sketches", "Freddie Freeloader" ],
"artist" : {
"name" : "Miles Davis",
"birthDate" : -1376035200000
}
}

Map 序列化

向 Album 中添加如下内容:

1
2
3
4
5
6
7
private Map<String, String> musicians = new HashMap<>();
public Map<String, String> getMusicians(){
return Collections.unmodifiableMap(musicians);
}
public void addMusician(String key, String value){
musicians.put(key, value);
}

在 main 中添加如下内容:

1
2
3
album.addMusician("Miles Davis", "Trumpet, Band leader");
album.addMusician("Julian Adderley", "Alto Saxophone");
album.addMusician("Paul Chambers", "double bass");

输出如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"title" : "Kind Of Blue",
"links" : [ "link1", "link2" ],
"songs" : [ "So what", "Flamenco Sketches", "Freddie Freeloader" ],
"artist" : {
"name" : "Miles Davis",
"birthDate" : -1376035200000
},
"musicians" : {
"Miles Davis" : "Trumpet, Band leader",
"Paul Chambers" : "double bass",
"Julian Adderley" : "Alto Saxophone"
}
}

其他

设置输出时间格式

1
2
SimpleDateFormat outputFormat = new SimpleDateFormat("dd MMM yyyy");
mapper.setDateFormat(outputFormat);

让Map按序输出

1
mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);

此时输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"title" : "Kind Of Blue",
"links" : [ "link1", "link2" ],
"songs" : [ "So what", "Flamenco Sketches", "Freddie Freeloader" ],
"artist" : {
"name" : "Miles Davis",
"birthDate" : "26 May 1926"
},
"musicians" : {
"Julian Adderley" : "Alto Saxophone",
"Miles Davis" : "Trumpet, Band leader",
"Paul Chambers" : "double bass"
}
}

使用 Tree Model 进行转换

我们继续使用上面的例子,来演示 Tree Model 的使用。使用 Tree 进行输出包含如下几个步骤:

  • 创建 JsonNodeFactory,用于创建 node。
  • 使用JsonFactory创建 JsonGenerator,并指定输出方法。
  • 创建ObjectMapper,它使用 JsonGenerator 和树的根节点输出到JSON。

如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
public class SerializationExampleTreeModel{
public static void main(String[] args) throws IOException{
JsonNodeFactory factory = new JsonNodeFactory(false);

JsonFactory jsonFactory = new JsonFactory();
JsonGenerator generator = jsonFactory.createGenerator(System.out);

ObjectMapper mapper = new ObjectMapper();
ObjectNode album = factory.objectNode();
mapper.writeTree(generator, album);
}
}

由于没有添加任何实质性内容,所以输出为:

{}

开始添加内容:

1
album.put("Album-Title", "Kind Of Blue");

JSON:

1
{"Album-Title":"Kind Of Blue"}

添加数组:

1
2
3
ArrayNode links = factory.arrayNode();
links.add("link1").add("link2");
album.set("links", links);

JSON:

1
{"Album-Title":"Kind Of Blue","links":["link1","link2"]}

添加对象:

1
2
3
4
ObjectNode artist = factory.objectNode();
artist.put("Artist-Name", "Miles Davis");
artist.put("birthDate", "26 May 1926");
album.set("artist", artist);

JSON:

1
{"Album-Title":"Kind Of Blue","links":["link1","link2"],"artist":{"Artist-Name":"Miles Davis","birthDate":"26 May 1926"}}

添加 musicians:

1
2
3
4
ObjectNode musicians = factory.objectNode();
musicians.put("Julian Adderley", "Alto Saxophone");
musicians.put("Miles Davis", "Trumpet, Band leader");
album.set("musicians", musicians);

JSON:

1
{"Album-Title":"Kind Of Blue","links":["link1","link2"],"artist":{"Artist-Name":"Miles Davis","birthDate":"26 May 1926"},"musicians":{"Julian Adderley":"Alto Saxophone","Miles Davis":"Trumpet, Band leader"}}

注解包

@JsonIgnoreProperties

类注解, 作用是json序列化时将java bean中的一些属性忽略掉,序列化和反序列化都受影响。用法很简单@JsonIgnoreProperties({“property1”,”property2”}),Hibernate延时加载

因为jsonplugin用的是java的内审机制.hibernate会给被管理的pojo加入一个 hibernateLazyInitializer属性,jsonplugin会把hibernateLazyInitializer也拿出来操作,并读取里面一个不能被反射操作的属性就产生了这个异常,可以用annotation来排除hibernateLazyInitializer这个属性。

@JsonIgnore

作用于属性或字段上,用来表明,当生成json的时候忽略有该annotation的方法或字段

@JsonProperty(“firstName”)

作用于属性或字段上,重命名

@JsonFormat

作用于属性或者字段上,方便的把Date类型直接转化为我们想要的模式,如@JsonFormat(pattern =”yyyy-MM-dd HH-mm-ss”)

@JsonSerialize

作用于属性或者字段上,指定序列化方式 @JsonSerialize(as=BasicType.class) 将类型序列化成指定类型 @JsonSerialize(using=CustomDoubleSerialize.class) 作用于属性或者字段上,用于在序列化时嵌入我们自定义的代码,比如序列化一个double时在其后面限制两位小数点。

@JsonSerialize(using= CustomDoubleSerialize.class)

1
2
3
4
5
6
7
8
9
10
11
12
13
publicclass CustomDateDeserialize extends JsonDeserializer<Date> {
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
public Date deserialize(JsonParser jp,DeserializationContext ctxt)
throws IOException,JsonProcessingException {
Date date = null;
try {
date =sdf.parse(jp.getText());
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
}

@JsonDeserialize

作用于属性或者字段上,指定反序列化方式 @JsonDeserialize(as=ValueImpl.class) 将类型反序列化成指定类型 @JsonDeserialize(using= CustomDateDeserialize.class) 用于在反序列化时嵌入我们自定义的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
publicclass CustomDateDeserialize extends JsonDeserializer<Date> {
private SimpleDateFormat sdf = newSimpleDateFormat("yyyy-MM-dd");
@Override
public Date deserialize(JsonParser jp,DeserializationContext ctxt)
throws IOException,JsonProcessingException {
Date date = null;
try {
date =sdf.parse(jp.getText());
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
}

@JsonCreator

作用于使用构造器方法或工厂方法 ,指定反序列化时创建实例方式(默认使用无参数构造器)

采用构造器方式

1
2
3
4
5
6
7
8
9
10
11
12
13
publicclass MyBean {
private int value;

@JsonCreator

publicMyBean(@JsonProperty("value") int v) {
this.value = v;

}

public int getValue() { return value; }

}

使用相同的方式,可以将@JsonCreator用在静态工厂方法上

不过,还有一个可选的替代方案,被称作“授权式”构建器(“delegating” creator):

1
2
3
4
5
6
7
8
9
10
public class DelegatingPOJO {

private final int _x, _y;

@JsonCreator
publicDelegatingPOJO(Map<String,Object> delegate) {
_x = (Integer)delegate.get("x");
_y = (Integer)delegate.get("y");
}
}

@JsonTypeInfo

类注解,当输出操作的对象拥有多个子类型且在反序列化时需要添加子类对象的类型信息,使用此注解可以正确地设置子类对象的类型

@JsonTypeInfo(use=Id.CLASS,include=As.PROPERTY,property=”class”)

子类类型作为属性,属性名为class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
"animals": [ {
"class" :"jackson.Lion",
"name" : "Simba",
"sound" : "Roar",
"type" : "carnivorous",
"endangered" : true
}]

@JsonTypeInfo(use=Id.CLASS,include= As.WRAPPER_OBJECT)
"animals": [ {
"jackson.Lion" : {
"name" : "Simba",
"sound" : "Roar",
"type" :"carnivorous",
"endangered" : true
}
}]

@JsonAutoDetect

类注解,指定属性发现规则

Jackson默认的属性发现规则将会查找到如下所述的属性:

•所有被public修饰的字段(成员变量);

•所有被public修饰的getter(即形如“getXxx()”的方法);

•所有被public修饰的setter(即形如“setXxx(value)”的方法)

@JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY)

@JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.NONE)