文章目录
Jackson Json 快速入门
Java对象转换为Json
总体来说,从Java到Json,Jakson提供了三种方式:Java对象、JsonNode Tree、Json流。因为是要快速入门,所以下文中主要使用第一种方式,也就是通过ObjectMapper实现从Java到Json以及从Json到Java的功能。详细教程传送门;基本上是使用ObjectMapper的write型API。
POJO的转换
创建User类:
将其转换为字符串并输出到控制台,结果如下:
public class User {
protected String name;
protected int id;
public User(){
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", id=" + id +
'}';
}
}
public static void main(String[] args){
User user=new User();
user.setId(666);
user.setName("落花流水存心阁");
String userJson=writer.writeValueAsString(user);
System.out.println(userJson);
}
//输出
{
"name" : "落花流水存心阁",
"id" : 666
}
多态条件下的转换
创建User类的子类VIP以及SuperVIP类:
public class SuperVIP extends User {
private String[] privileges;
public String[] getPrivileges() {
return privileges;
}
public void setPrivileges(String[] privileges) {
this.privileges = privileges;
}
public SuperVIP(String[] privileges) {
this.privileges = privileges;
}
public SuperVIP() {
}
@Override
public String toString() {
return "SuperVIP{" +
"privileges=" + Arrays.toString(privileges) +
", name='" + name + '\'' +
", id=" + id +
'}';
}
}
public class VIP extends User{
private String privilege;
public VIP() {
}
public VIP(String privilege) {
this.privilege = privilege;
}
public String getPrivilege() {
return privilege;
}
public void setPrivilege(String privilege) {
this.privilege = privilege;
}
@Override
public String toString() {
return "VIP{" +
"privilege='" + privilege + '\'' +
", name='" + name + '\'' +
", id=" + id +
'}';
}
}
public static void main(String[] args){
String basicPrivilege="超大容量";
VIP vip=new VIP(basicPrivilege);
vip.setId(777);
vip.setName("落花流水存心阁");
String vipJson=writer.writeValueAsString(vip);
System.out.println(vipJson);
// writer.writeValue(System.out,vip);
// System.out.println("我不会出现");
String superPrivilege="高速下载";
String[] privileges=new String[2];
privileges[0]=basicPrivilege;
privileges[1]=superPrivilege;
SuperVIP superVIP=new SuperVIP(privileges);
superVIP.setId(888);
superVIP.setName("落花流水存心阁");
String superVipJson=writer.writeValueAsString(superVIP);
System.out.println(superVipJson);
String privilegeJson=writer.writeValueAsString(privileges);
System.out.println(privilegeJson);
}
//输出
{
"name" : "落花流水存心阁",
"id" : 777,
"privilege" : "超大容量"
}
{
"name" : "落花流水存心阁",
"id" : 888,
"privileges" : [ "超大容量", "高速下载" ]
}
集合转换
创建User的List,然后将其转换为Json字符串,输出到控制台:
public static void main(String[] args){
List<User> users=new ArrayList<>(3);
users.add(user);
users.add(vip);
users.add(superVIP);
System.out.println(mapper.writeValueAsString(users));
}
//输出
[{"name":"落花流水存心阁","id":666},{"name":"落花流水存心阁","id":777,"privilege":"超大容量"},{"name":"落花流水存心阁","id":888,"privileges":["超大容量","高速下载"]}]
会发现这里虽然结果ok,但是这样的Json是无法反序列化的,因为使用Jackson并不知道该Json字符串同类的关联,也就无法创建对象了。
为User类添加关于类型的注释并在序列化时提供相关信息:
@JsonTypeInfo(use =JsonTypeInfo.Id.CLASS, property = "@class")
@JsonSubTypes({ @Type(value = VIP.class, name = "vip"), @Type(value = SuperVIP.class, name = "supervip") })
public class User{}
public static void main(String[] args){
List<User> users=new ArrayList<>(3);
users.add(user);
users.add(vip);
users.add(superVIP);
String usersJson=mapper.writerFor(new TypeReference<List<User>>() {
}).writeValueAsString(users);
System.out.println(usersJson);
}
输出:
[{"@class":"com.xiaomo.util.json.example.fast_understand.User","name":"落花流水存心阁","id":666},{"@class":"com.xiaomo.util.json.example.fast_understand.VIP","name":"落花流水存心阁","id":777,"privilege":"超大容量"},{"@class":"com.xiaomo.util.json.example.fast_understand.SuperVIP","name":"落花流水存心阁","id":888,"privileges":["超大容量","高速下载"]}]
因为泛型在编译的时候擦除了类信息,所以这里使用了TypeReference这一在运行时标记目标List类别的对象;
Json转换为Java对象
我们将上一节的输出,作为这一节的输入~ 相应的,我们使用ObjectMapperd对象的read系API。
转换为POJO
操作比较常规,传入相对应的class对象即可:
String userJson="{\n" +
" \"@class\" : \"com.xiaomo.util.json.example.fast_understand.User\",\n" +
" \"name\" : \"落花流水存心阁\",\n" +
" \"id\" : 666\n" +
"}";
//转换为POJO
User user=objectMapper.readValue(userJson,User.class);
System.out.println("普通用户的用户名:"+user.getName());
多态条件的转换
String vipJson="{\n" +
" \"@class\" : \"com.xiaomo.util.json.example.fast_understand.VIP\",\n" +
" \"name\" : \"落花流水存心阁\",\n" +
" \"id\" : 777,\n" +
" \"privilege\" : \"超大容量\"\n" +
"}";
String superVipJson="{\n" +
" \"@class\" : \"com.xiaomo.util.json.example.fast_understand.SuperVIP\",\n" +
" \"name\" : \"落花流水存心阁\",\n" +
" \"id\" : 888,\n" +
" \"privileges\" : [ \"超大容量\", \"高速下载\" ]\n" +
"}";
//多态条件下的转换
User vip=objectMapper.readValue(vipJson,User.class);
System.out.println("VIP的用户名:"+vip.getName());
System.out.println("通过父类反序列化的VIP是不是VIP:"+(vip instanceof VIP));
SuperVIP superVIP=objectMapper.readValue(superVipJson,SuperVIP.class);
System.out.println("SuperVIP的权限:");
for(String s:superVIP.getPrivileges()){
System.out.println(s);
}
这里,我们使用的是含类信息的Json字符串,此时可以传入父类的class。因为Json字符串里已经包含了Jackson所需要的创建对象的信息。
如果使用不含类信息的Json字符串,则应该使用对应类的class对象。
集合转换
String userListJson="[{\"@class\":\"com.xiaomo.util.json.example.fast_understand.User\",\"name\":\"落花流水存心阁\",\"id\":666},{\"@class\":\"com.xiaomo.util.json.example.fast_understand.VIP\",\"name\":\"落花流水存心阁\",\"id\":777,\"privilege\":\"超大容量\"},{\"@class\":\"com.xiaomo.util.json.example.fast_understand.SuperVIP\",\"name\":\"落花流水存心阁\",\"id\":888,\"privileges\":[\"超大容量\",\"高速下载\"]}]\n";
//有类信息的集合转换
List<User> userList=objectMapper.readValue(userListJson,new TypeReference<List<User>>(){});
System.out.println("集合转换结果");
for(User u:userList){
System.out.println(u);
}
集合转换时,需要注意的是使用含有类信息的Json字符串,同时与序列化一样,需要传入标志集合泛型类别的TypeReference;
Jackson Json 注解
注:以下具体代码示例见 Ignore fields in JSON using Jackson;
- 类级别的忽略字段注解:@JsonIgnoreProperties
- 字段级别的忽略注解:@JsonIgnore
注:以下具体代码示例见 Json annotations and dynamic beans;
- 关联Java字段和Json属性的注解:@JsonProperty
- 指定反序列化时所使用的构造函数的注解:@JsonCreator
- 指定处理无法和Java字段对应的Json属性的getter与setter方法,多用于反序列化时处理多余或者不想处理的Json属性:@JsonAnyGetter和@JsonAnySetter
注:以下具体代码示例见 Jackson List serialization和Json Polymorphism;
- 在Json字符串中存储类信息的注解:@JsonTypeInfo,使用于父类,指定类信息的属性名以及对应属性值的值。@JsonSubTypes,使用于父类,指定子类;
需要注意的是:使用ObjectMapper对象输出Json结果时,可以指定输出流,但是输出后Jackson(JsonFactory)将尝试关闭该流;所以如何指定System.out为输出流,则以后out流关闭,控制台再也看不到结果。以下为源代码中writeValue的注释:
Note: method does not close the underlying stream explicitly
here; however, {@link JsonFactory} this mapper uses may choose
to close the stream depending on its settings (by default,
it will try to close it when {@link JsonGenerator} we construct
is closed).
项目源码免费获取 个人博客,百度网盘地址+提取码,文件无密~