网站设计制作从哪里学起,济南it培训机构,百度商桥代码怎么添加到网站,js网站大全如果不了解JSON格式#xff0c;建议先看下#xff1a;JSON数据格式【学习记录】
JSON序列化、反序列化JavaBean的框架有很多#xff0c;最常见的Jackson、阿里巴巴开源的FastJson、谷歌的GSON、apache提供的json-lib等#xff0c;下面我们主要来熟悉一下#xff1a;Java语…如果不了解JSON格式建议先看下JSON数据格式【学习记录】
JSON序列化、反序列化JavaBean的框架有很多最常见的Jackson、阿里巴巴开源的FastJson、谷歌的GSON、apache提供的json-lib等下面我们主要来熟悉一下Java语言中FastJson的使用。
FastJson FastJson是由阿里巴巴工程师基于Java开发的一款Json解析器和生成器可用于将Java对象转换为其JSON表示形式它还可以用于将JSON字符串转换为等效的Java对象。FastJson可以处理任意Java对象包括没有源代码的预先存在的对象。 FastJson使用十分简便我们只需要在Maven工程的pom文件中引入以下依赖即可
dependencygroupIdcom.alibaba/groupIdartifactIdfastjson/artifactIdversion1.2.73/version
/dependencyFastJson API的入口是com.alibaba.fastjson.JSON常用的序列化操作都可以在JSON类上的静态方法直接完成。
API测试
我们已经在项目中引入了FastJson的依赖我们再创建一个用户类用于测试
package com.test.json;import lombok.Data;Data
public class User {private Integer id;private String name;private String sex;private Integer age;public User(Builder builder) {this.id builder.id;this.name builder.name;this.sex builder.sex;this.age builder.age;}public static Builder builder() {return new Builder();}public static class Builder {private Integer id;private String name;private String sex;private Integer age;public Builder name(String name) {this.name name;return this;}public Builder sex(String sex) {this.sex sex;return this;}public Builder age(int age) {this.age age;return this;}public Builder id(int id) {this.id id;return this;}public User build() {return new User(this);}}
}一、序列化
序列化就是将JavaBean序列化为JSON字符串下面我们来看下FastJson常见的序列化方法。
下面序列化相关方法都有统一的返回值类型String。
1toJsonString(Object o);
public static void main(String[] args) {User user User.builder().id(1).name(张三).sex(男).age(23).build();System.out.println(JSON.toJSONString(user));
}{age:23,id:1,name:张三,sex:男}我们通过传入一个对象便可以将对象转成JSON字符串这里我们传入的不仅仅是JavaBean还可以是一个Map对象传入Map对象我们同样也可以取到一个JSON字符串。
public static void main(String[] args) {MapString, Object userMap new HashMap();userMap.put(id, 1);userMap.put(name, 张三);userMap.put(sex, 男);userMap.put(age, 23);System.out.println(JSON.toJSONString(userMap));
}{age:23,id:1,name:张三,sex:男}List对象也很适用结果是一个标准的JSONArray的字符串。
public static void main(String[] args) {User zhangsan User.build().id(1).name(张三).sex(男).age(23).build();User lisi User.build().id(2).name(李四).sex(女).age(18).build();ListUser userList new ArrayList();userList.add(zhangsan);userList.add(lisi);System.out.println(JSON.toJSONString(userList));
}[{id:1,name:张三,sex:男,age:23},{id:2,name:李四,sex:女,age:18}]2toJSONString(Object o, boolean prettyFormat);
如果说 toJSONString(Object o); 的输出结果只有单调的一行让你看起来有点吃力那么我们可以使用 toJSONString(Object o, boolean prettyFormat); 来让输出结果看起来舒服点。
public static void main(String[] args) {User user User.builder().id(1).name(张三).sex(男).age(23).build();System.out.println(JSON.toJSONString(user, true));
}{age:23,id:1,name:张三,sex:男
}通过JSON自带的格式化让输出结果看起来更加清晰真是贴心~
3JSON.toJSONString(Object object, SerializerFeature… features);
我们可以看到这个方法里面有个参数SerializerFeature...可能感到有点陌生我们先来看下什么是 SerializerFeature 通过源码可以发现 SerializerFeature 原来是个枚举类 源码中都被 deprecated 注释的实例说明已经废弃了那有哪些是我们平时经常用到的呢
对象描述SerializerFeature.UseSingleQuotes使用单引号而不是双引号默认为falseSerializerFeature.PrettyFormat结果是否格式化默认为falseSerializerFeature.WriteDateUseDateFormat如果时间是date、时间戳类型按照这种格式yyyy-MM-dd HH:mm初始化时间SerializerFeature.WriteMapNullValue是否输出值为null的字段默认为falseSerializerFeature.WriteClassName序列化时写入类型信息默认为false
使用案例
SerializerFeature.UseSingleQuotes
使用单引号而不是使用双引号默认为false。
public static void main(String[] args) {User user User.builder().id(1).name(张三).sex(男).age(23).build();System.out.println(JSON.toJSONString(user, SerializerFeature.UseSingleQuotes));
}{age:23,id:1,name:张三,sex:男}SerializerFeature.PrettyFormat
结果是否格式化默认为false。
public static void main(String[] args) {User user User.builder().id(1).name(张三).sex(男).age(23).build();System.out.println(JSON.toJSONString(user));System.out.println();System.out.println(JSON.toJSONString(user, SerializerFeature.PrettyFormat));
}{age:23,id:1,name:张三,sex:男}{age:23,id:1,name:张三,sex:男
}SerializerFeature.WriteDateUseDateFormat
如果时间是Date、时间戳类型按照这种格式初始化时间yyyy-MM-dd HH:mm。
public static void main(String[] args) {System.out.println(JSON.toJSONString(new Date()));System.out.println();System.out.println(JSON.toJSONString(new Date(), SerializerFeature.WriteDateUseDateFormat));
}16764275766912023-02-15 10:19:37通过这种方式我们将日期输出成了固定的格式yyyy-MM-dd HH:mm有时候我们不想得到这种格式那该怎么办通过下面方法支持自定义时间格式注意方法不要用错
4toJSONStringWithDateFormat(Object object, String dateFormat, SerializerFeature… features);
public static void main(String[] args) {System.out.println(JSON.toJSONString(new Date()));System.out.println();System.out.println(JSON.toJSONStringWithDateFormat(new Date(), HH:mm:ss));
}167642835077110:32:30下面我们接着看SerializerFeature枚举类的其他用法。
SerializerFeature.WriteMapNullValue
是否输出值为null的字段默认为false。
这个有什么用处呢我们应该很清楚开发规范中鼓励用JavaBean传递参数尽量减少Map传递参数因为Map相当于一个黑盒对于使用者来说根本不知道里面存在哪些字段而对于创建者来说估计也时常会忘记里面存在哪些字段为了解决这个痛JSON也推出了解决方法
public static void main(String[] args) {MapString, Object dataMap new HashMap();dataMap.put(name, null);dataMap.put(age, 23);System.out.println(JSON.toJSONString(dataMap));System.out.println();System.out.println(JSON.toJSONString(dataMap, SerializerFeature.WriteMapNullValue));
}{age:23}{name:null,age:23}通过普通方式的 toJSONString() 方法空值仿佛被吃掉了这很可能会成为一个开发灾难
SerializerFeature.WriteClassName
序列化时写入类信息默认为false。这个方法可以在反序列化的时候用到用法如下
public static void main(String[] args) {User user User.builder().id(1).name(张三).sex(男).age(23).build();System.out.println(JSON.toJSONString(user, SerializerFeature.WriteClssName));
}{type:com.test.json.User,age:23,id:1,name:张三,sex:男}通过这样我们可以看到我们序列化的对象是什么类型的。
上面这些便是toJSONString的扩展用法上面说到的是序列化那么对应的便是反序列化。
二、反序列化
反序列化就是把JSON格式的字符串转换为JavaBean对象。
1JSONObject parseObject(String text);
public static void main(String[] args){String jsonStr {age:23,id:1,name:张三,sex:男};JSONObject jsonObject JSON.parseObject(jsonStr);System.out.println(jsonObject.get(name));
}张三用法十分简单可以将一个标准的JSON字符串转为一个JSONObject对象由于JSONObject类实现了Map接口因此我们可以通过get()来获取到值。
我们上述已经说过Map的致命不足所以我们更希望能得到一个JavaBean对象。
2T T parseObject(String text, ClassT clazz);
我们通过传入我们想要转换的对象类型就可以得到我们想要的JavaBean。
public static void main(String[] args){String jsonStr {age:23,id:1,name:张三,sex:男};User user JSON.parseObject(jsonStr, User.class);System.out.println(user.getName());
}张三除了基本反序列化之外还有一种泛型反序列化可提供使用。
3T T parseObject(String text, TypeReferenceT type, Feature... features);
通过泛型我们就可以不用传入一个Class对象而直接获取到我们的JavaBean。
public static void main(String[] args){String jsonStr {age:23,id:1,name:张三,sex:男};User user JSON.parseObject(jsonStr, new TypeReferenceUser(){});System.out.println(user.getName());
}张三FastJson序列化还有一个用处那便是进行深克隆。软件设计模式中原型模式涉及到的深克隆和浅克隆。
浅克隆的实现方式十分简单我们只需要实现Cloneable接口然后重写clone()方法
Data
class Person {private String name;
}Data
class NiceCard implements Cloneable {public Person person;public void award() {System.out.println(this.person.getName() 获得好人卡一张);}public NiceCard clone() throws CloneNotSupportedException {return (NiceCard)super.clone();}
}public class TestClient {public static void main(String[] args) {NiceCard niceCard new NiceCard();Person person new Person();person.setName(小李);niceCard.setPerson(person);NiceCard cloneCard niceCard.clone();Persson clonePerson cloneCard.getPerson();clonePerson.setName(小王);niceCard.award();cloneCard.award();System.out.println(person clonePerson);}
}小王获得一张好人卡
小王获得一张好人卡
true结果中我们可以看到好人卡都是属于小王的这就是浅克隆的弊端了。
我们要想实现深克隆有许多种方式
手动为引用属性赋值借助FastJson使用Java流的序列化对象
方法有很多我们重点看下FastJson的实现方式
public static void main(String[] args) {NiceCard niceCard new NiceCard();Person person new Person();person.setName(小李);niceCard.setPerson(person);//借助FastJsonNiceCard cloneCard JSON.parseObject(JSON.toJSONString(niceCard), NiceCard.class);Person clonePerson cloneCard.getPerson();clonePerson.setName(小王);niceCard.award();cloneCard.award();System.out.println(person clonePerson);
}小李获得好人卡一张
小王获得好人卡一张
false通过FastJson反序列化我们得到的两个对象实际上是不同的这也很方便的实现了深克隆。
4T ListT parseArray(String text, ClassT clazz);
这是将一个JSON字符串转为JSONArray的方法。
public static void main(String[] args) {String jsonStr [{\id\:1,\name\:\张三\,\sex\:\男\,\age\:23},{\id\:2,\name\:\李四\,\sex\:\女\,\age\:18}];ListUser userList JSON.parseArray(jsonStr, User.class);userList.forEach(System.out::println);
}User(id1, name张三, sex男, age23)
User(id2, name李四, sex女, age18)同样我们也可以通过使用泛型序列化来实现同样的功能
5ListObject parseArray(String text, Type[] types);
public static void main(String[] args) {String jsonStr [{\id\:1,\name\:\张三\,\sex\:\男\,\age\:23},{\id\:2,\name\:\李四\,\sex\:\女\,\age\:18}];Type type new TypeReferenceUser() {}.getType();JSON.parseArray(jsonStr, new Type[]{type, type}).forEach(System.out::println);
}这种方式有个坑就是我们使用parseArray()这个方法的时候第二个参数需要传入我们要反序列化的对象类型但是我们这里需要传入的是数组不知道你有没有为数组里面放了两个一样的type感到奇怪没错这就是方法的坑我们List里面有多少个对象Type[]这个数组里面的个数要与之匹配不然会抛出以下错误 上述JSON串中对象的类型都为User如果JSON串中存在不同的类型时
public static void main(String[] args) {String jsonStr [{\id\:1,\name\:\张三\,\sex\:\男\,\age\:23},{\stuName\:\李四\}];Type userType new TypeReferenceUser() {}.getType();Type studentType new TypeReferenceStudent() {}.getType();JSON.parseArray(jsonStr, new Type[]{userType,studentType}).forEach(System.out::println);
}User(id1, name张三, sex男, age23)
Student(stuName李四)如果将userType和studentType调换顺序则结果
Student(stuNamenull)
User(idnull, namenull, sexnull, agenull)三、JavaBean转换为Byte[]
1toJSONBytes(Object o)
我们平时在进行网络通讯的时候需要将对象转为字节然后进行传输。我们使用字符串的时候字符串中有个很便捷的API可以将字符串转为字节数组。
String str 张三;
byte[] bytes str.getBytes();但是我们要将一个JavaBean对象转为字节数组的时候我们得借助ByteArrayOutputStream流的帮助。
public static void main(String[] args) {byte[] bytes null;ByteArrayOutputStream bos new ByteArrayOutputStream();try{ObjectOutputStream oos new ObjectOutputStream(bos);oos.writeObject(obj);oos.flush();bytes bos.toByteArray();oos.close();bos.close();} catch(IOException ex) {ex.printStackTrace();}
}这种方式也可以很好的将JavaBean对象转为字节数组但是代码不免有点多了而FastJson中野提供了很方便的API以供使用。
public static void main(String[] args) {User user User.builder().id(1).name(张三).sex(男).age(23).build();//JavaBean对象转为字节数组byte[] bytes JSON.toJSONBytes(user);
}我们要将字节数组转为对象FastJson也同样支持
public static void main(String[] args) {User user User.builder().id(1).name(张三).sex(男).age(23).build();//JavaBean对象转为字节数组byte[] bytes JSON.toJSONBytes(user);//将字节数组转为JavaBean对象Object obj JSON.parseObject(bytes, User.class, Feature.IgnoreNotMatch);System.out.println(obj);
}//待更新…