本文介绍json的规范及javascript和java对数据的交换读取
1. json介绍
1.1 json简介
JSON(JavaScript Object Notation, JS对象简谱)是一种轻量级的数据交换格式。
它基于 ECMAScript(European Computer Manufacturers Association, 欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。
简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。
易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
1.2为什么使用 JSON?
对于 AJAX 应用程序来说,JSON 比 XML 更快更易使用:
使用 XML
- 读取 XML 文档
- 使用 XML DOM 来循环遍历文档
- 读取值并存储在变量中
使用 JSON
- 读取 JSON 字符串
- 用 eval() 处理 JSON 字符串
2. json规范
2.1基础规范
eg:
{
"name":"蒋增奎","address":"天府大道","age":30, "isMoney":true
}
规范说明:
- json内容需要用花括号{}包裹起来
- 键值对用:间隔,多个键,中间用逗号隔离,最后一个键不需要逗号
- 键key如果没有特殊符号,可以不用双引号包围。
- 值的类型,包括字符串、数字、布尔值、对象、数组五种类型,前三种最常见
key可以不需要双引号如:
2.2 key值为-字符串、数字、布尔值
{
name:"蒋增奎",address:"天府大道",age:30, isMoney:true
}
2.3 key值为对象Object
嵌套就是json对象里面又包含对象,key对应的值,除了括字符串、数字、布尔值三种类型外,还可以是一个对象,其规范是
key:{对象属性}
var obj4 = {
name: "雪邦科技",
boss: {
name: "蒋增奎--",
age: 40,
},
};
2.4 key值为数组
数组用方括号包围一起来[x1,x2,x3],分组之间用逗号隔离
数组值有两种类型:
1.基本类型:如[1,2,3]
2.json对象,json对象要用{}包裹
//---------------------------------------------
var obj2={
wifes: ["冰冰", "雅致"], //基础类型,对应后端是一个基础类型的数组或者list
"user":[ //是一个对象,对应后都是一个对象的数组或者List
{"name":"jzk","sex":20},
{"name":"jj","sex":30},
],
"address":[
{"shen":"云南","city":"昆明"},
{"shen":"四川","city":"雅安"},
]
};
//---------------------------------------------
var obj3={
"name":"雪邦科技",
"address":"天府大道",
"employees": [
{ "firstName":"Bill" , "lastName":"Gates" },
{ "firstName":"George" , "lastName":"Bush" },
{ "firstName":"Thomas" , "lastName":"Carter" }
]
}
2.5 json本身就是一个数组
有两种类型:
1.基本类型数组:[3,2,1]
2.对象的数组:[{x1},{x2},{x3},] 对象要用{}包括
var obj1=[
{"name":"蒋增奎","address":"天府大道","sex":30},
{"name":"奎奎","address":"大道","sex":38},
];
var obj2=[1,2,3];
3.javascript操作json
语法:
- 把json赋值一个给一本变量,通过变量直接用对象名.key就可以读取
- 如果是数组,则可以循环,obj[i]读取
- 如果key值为对象,直接用:对象名.key.属性读取
- 如果要修改值,直接用对象名.key=xxx则可以修改
3.1 javascript操作json对象
eg:
<script>
function dd() {
//1.基本属性读取=========================
var obj = {
name: "蒋增奎1",
address: "天府大道",
sex: 30,
exist: true,
};
alert(obj.name);
obj.name = "jzk"; //改变属性值
//2.key值为对象==========================
var obj4 = {
name: "雪邦科技",
boss: {
name: "蒋增奎--",
age: 40,
},
};
alert("obj4.boss.name=" + obj4.boss.name);
//3.json本身是一个数组====================
var obj1 = [
{ name: "蒋增奎", address: "天府大道", sex: 30 },
{ name: "奎奎", address: "大道", sex: 38 },
];
//循环读取
for (index in obj1) {
alert(
"数组[" +
index +
"]=" +
obj1[index].name +
"-" +
obj1[index].address +
"-" +
obj1[index].sex
);
}
//4.key值是一个数组
var company = {
name: "雪邦",
address: "天府大道1号",
boss: "蒋增奎",
exist: true,
tax: 5000,
users: [
{ name: "蒋增奎", sex: "男", mobile: "13688006645" },
{ name: "张三", sex: "女", mobile: "13688006640" },
],
};
var users = company.users;
for (index in users) {
alert(
"company.users数组[" +
index +
"]=" +
users[index].name +
"-" +
users[index].mobile +
"-" +
users[index].sex
);
}
}
</script>
3.2 js操作json字符串,把字符串转化为json对象
有两种写法:
(1)JSON.parse(字符串)
(2) eval (“(” + txt + “)”);
eg:
<script>
function dd() {
//1.eval((json字符串))语法转换成json对象
var s = '{"name":"蒋增奎","address":"天府大道","sex":30}';
s = "(" + s + ")";
var obj5 = eval(s);
alert(obj5.sex);
// 2.JSON.parse(json字符串)语法转换成json对象
var txt =
'{ "sites" : [' +
'{ "name":"菜鸟教程" , "url":"www.runoob.com" },' +
'{ "name":"google" , "url":"www.google.com" },' +
'{ "name":"微博" , "url":"www.weibo.com" } ]}';
var obj6 = JSON.parse(txt);
alert(obj6.sites[0].name);
}
</script>
3.3 键值为null或者键不存在判断
如果键值为null.可以直接用:obj.sex == null判断
如果键不存在,用:typeof obj.deptId == "undefined"判断
function dd2() {
var obj = {
name: "蒋增奎1",
address: "天府大道",
sex: null,
exist: true,
deptId: 3,
};
//如果获取得一个键key本身不存在
if (!obj.deptId) {
alert("不存在obj.deptId");
}
if (obj.deptId == null) {
alert("不存在obj.deptId");
}
alert(obj.deptId);
//存在key,但值为null
if (!obj.sex) {
alert("不存在obj.sex");
}
//存在key,但值为null
if (obj.sex == null) {
alert("obj.sex==null");
}
alert(obj.sex);
//通过typeof可以判断出是否是null还是key不存在
if (typeof obj.deptId == "undefined") {
alert("key==deptId不存在");
}
//排除掉无key和key值为null
if (typeof obj.deptId != "undefined" && obj.deptId) {
alert("key==deptId存在并且值不为null");
}
}
3.4json对象转字符串
var str=JSON.stringify(json对象)
function dd1() {
var obj = { name: "runoob", alexa: 10000, site: "www.runoob.com" };
var JSONStr = JSON.stringify(obj);
alert(JSONStr);
}
4.java操作json
Java中并没有内置JSON的解析,因此使用JSON需要借助第三方类库。
下面是几个常用的 JSON 解析类库:
- Gson: 谷歌开发的 JSON 库,功能十分全面。
- FastJson: 阿里巴巴开发的 JSON 库,性能十分优秀。
- Jackson: 社区十分活跃且更新速度很快。,springMVC默认
4.1准备两个比较全面的VO类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class JsonVO {
private Long id;
private String name;
private BigDecimal weight;//年纪
private Date birth;
private Date creatTime;
private Boolean money;
private Address address;
private List<Address> addresses;
private Map<String,Object> son;
private String[] wifes;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Address {
private String shen;
private String city;
}
4.1 FastJson介绍
4.1.1引入依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
4.1.2 vo基础解析
最基础,直接调用JSON.toJSONString(vo);
/**
* 问题:
* 1.vo对象属性为null不会传递
* 2.日期转化成时间戳数字
*
*/
@Test
public void test2(){
//--------------vo转json-------------
JsonVO vo=new JsonVO();
vo.setId(1l);
vo.setBirth(new Date());
String jsonString = JSON.toJSONString(vo);
System.out.println("只传vo对象:"+jsonString);
}
打印效果
只传vo对象:{"birth":1701706009427,"id":1}
4.1.3 把null的字段全部传递过来,值显示为null
传入参数:SerializerFeature.WriteMapNullValue
问题:前端需要去处理null
@Test
public void test3(){
JsonVO vo=new JsonVO();
vo.setId(1l);
vo.setBirth(new Date());
String jsonString = "";
jsonString = JSON.toJSONString(vo,
SerializerFeature.WriteMapNullValue
);
System.out.println(jsonString);
}
效果
{"addresses":null,"birth":1701707310898,"creatTime":null,"id":1,
"money":null,"name":null,"weight":null}
4.1.4 字符串类型的null处理成""
null的字符串类型能传递,并转化成""
问题:
1.日期和自定义对象依然显示为nul
2.数组、list、数字、boolean无法传递
@Test
public void test4(){
JsonVO vo=new JsonVO();
vo.setId(1l);
vo.setBirth(new Date());
String jsonString = "";
jsonString = JSON.toJSONString(vo,
SerializerFeature.WriteNullStringAsEmpty //字符串为null的转化为""
);
System.out.println(jsonString);
}
效果
{"address":null,"birth":1701708039585,"creatTime":null,"id":1,"name":""}
4.1.5 数字、布尔、数组/list、日期null处理
SerializerFeature.WriteNullStringAsEmpty, //字符串为null的转化为""
SerializerFeature.WriteNullNumberAsZero, //数字为null转化为0
SerializerFeature.WriteNullListAsEmpty, //数组、list为null的转化成[]
SerializerFeature.WriteNullBooleanAsFalse,//布尔值为null转化成false
SerializerFeature.WriteDateUseDateFormat //日期把时间戳格式化
问题
1.日期、自定义的对象依然为null
2.如果数字0,和布尔值false有意义,前端区分不出来
3.日期区分不出来是时间还是日期
@Test
public void test5(){
JsonVO vo=new JsonVO();
vo.setId(1l);
vo.setBirth(new Date());
String jsonString = "";
jsonString = JSON.toJSONString(vo,
SerializerFeature.WriteNullStringAsEmpty, //字符串为null的转化为""
SerializerFeature.WriteNullNumberAsZero, //数字为null转化为0
SerializerFeature.WriteNullListAsEmpty, //数组、list为null的转化成[]
SerializerFeature.WriteNullBooleanAsFalse,//布尔值为null转化成false
SerializerFeature.WriteDateUseDateFormat //日期把时间戳格式化
);
System.out.println(jsonString);
}
效果
{"address":null,"addresses":[],"birth":"2023-12-05 00:51:55",
"creatTime":null,"id":1,"money":false,"name":"","weight":0}
4.1.5 把null全部转化成""
重写过滤器,拦截null的,全部置换成""
问题:
1.前端如果有数字计算,要去转化
2.如果自定义对象,数组等,需要先判断""再做相关操作
过滤器
public class JsonUtil {
/**
* 过滤器,把null全部转化成空字符串
* @return
*/
public static ValueFilter getFilter(){
ValueFilter filter = new ValueFilter() {
@Override
public Object process(Object obj, String s, Object v) {
// System.out.println(s);
if(v==null)
return "";
return v;
}
};
return filter;
}
}
解析
{
"address":"","addresses":"","birth":1701709403555,"creatTime":"","id":1,
"money":"","name":"","weight":""
}
4.1.6日期转换
采用注解的方式,可以解析出日期和时间两种,此方法最完美
在日期变量属性上加:
@JSONField(format=“yyyy-MM-dd”)或者
@JSONField(format=“yyyy-MM-dd HH:mm:ss”)
vo
@Data
@NoArgsConstructor
@AllArgsConstructor
public class JsonVO {
private Long id;
private String name;
private BigDecimal weight;//年纪
@JSONField(format="yyyy-MM-dd")
private Date birth;
@JSONField(format="yyyy-MM-dd HH:mm:ss")
private Date creatTime;
private Boolean money;
private Address address;
private List<Address> addresses;
}
测试
@Test
public void test7(){
JsonVO vo=new JsonVO();
vo.setId(1l);
vo.setBirth(new Date());
vo.setCreatTime(new Date());
String jsonString = "";
jsonString = JSON.toJSONString(vo);
System.out.println(jsonString);
}
效果
{"birth":"2023-12-05","creatTime":"2023-12-05 01:07:51","id":1}
4.1.7 map处理
@Test
@Test
public void test8(){
Map<String,Object> map=new HashMap<String,Object>();
map.put("name","jzk");
map.put("id",1);
map.put("sex",null);
String jsonString = "";
jsonString = JSON.toJSONString(map,JsonUtil.getFilter());
System.out.println(jsonString);
}
效果:
{"sex":"","name":"jzk","id":1}
4.1.8 list处理
不需要特殊处理
@Test
public void test9(){
List<Address> list=new ArrayList<>();
list.add(new Address("四川","成都"));
list.add(new Address("四川","简阳"));
list.add(new Address());
String jsonString = "";
jsonString = JSON.toJSONString(list,JsonUtil.getFilter());
System.out.println(jsonString);
}
效果:
[{"city":"成都","shen":"四川"},{"city":"简阳","shen":"四川"},{"city":"","shen":""}]
4.1.9 总结
用过滤器还是最简单
4.1.10 json转java对象
采用语法VO vo=JSON.parseObject(jsonStr,VO.class);
如果key是"",其他对象可以转化成null
这里有两个特殊的:
- 数组转化成list
要用JSON.parseArray来转化,JSONArray 本身也是一个数组
2.数组转化成map
方法 | 说明 |
---|---|
SON.parseObject(jsonStgr,映射类.class); | json和一个类对应,不管这个vo类里属性有多复杂,都能映射上 |
Map<String,Object> map=JSON.parseObject(jsonStgr,Map.class); | 和map对象的映射 |
JSONArray jsonArray = JSONArray.parseArray(jsonStgr); | 返回一个数组,json本身也是一个数组 |
List< VO > list=JSON.parseArray(jsonStgr,VO.class); | 映射到一个List< VO > 列表里 |
@Test
public void test33(){
String txt="{'address':'','addresses':'','birth':'2023-12-05','creatTime':'','id':1,'money':'','name':'','weight':''}";
JsonVO vo= JSON.parseObject(txt,JsonVO.class);
System.out.println(vo);
//json有,但vo没有的字段,不报错,
//waihao这个属性,vo对象里没有
txt="{'name':'jzk','waihao':'李富贵'}";
vo= JSON.parseObject(txt,JsonVO.class);
System.out.println(vo);
//自定义对象
txt="{'address':{'city':'cd','shen':'sc'},'addresses':'','birth':'2023-12-05','creatTime':'','id':1,'money':'','name':'','weight':''}";
vo= JSON.parseObject(txt,JsonVO.class);
//数组
txt="{'address':'','addresses':[{'city':'cd','shen':'sc'},{'city':'my','shen':'sc'}],'birth':'2023-12-05','creatTime':'','id':1,'money':'','name':'','weight':''}";
vo= JSON.parseObject(txt,JsonVO.class);
System.out.println(vo);
//数组
txt="{'address':'','addresses':[{'city':'cd','shen':'sc'},{'city':'my','shen':'sc'}],'birth':'2023-12-05','creatTime':'','id':1,'money':'','name':'','weight':''}";
vo= JSON.parseObject(txt,JsonVO.class);
System.out.println(vo);
//-------------------特殊数据类型---------------------
//纯数组转list
txt="[{'city':'成都','shen':'四川'},{'city':'简阳','shen':'四川'},{'city':'','shen':''}]";
List<Address> list=JSON.parseArray(txt,Address.class);
for (Address a:list){
System.out.println(a);
}
//数组转数组,数组转数组没有直接方法,需要用JSONArray来过渡
System.out.println("数组转数组");
txt="[{'city':'成都','shen':'四川'},{'city':'简阳','shen':'四川'},{'city':'','shen':''}]";
JSONArray jsonArray = JSONArray.parseArray(txt);
Address[] ss=new Address[jsonArray.size()];
for(int i=0;i<jsonArray.size();i++){
Address address=jsonArray.getObject(i,Address.class);
ss[i]=address;
}
for (Address address:ss){
System.out.println(address);
}
//str转map
txt="{'city':'成都','shen':'四川'}";
Map<String,Object> map=JSON.parseObject(txt,Map.class);
for(String key:map.keySet()){
String value = map.get(key).toString();
System.out.println("key="+key+" vlaue="+value);
}
}
4.2 Gson介绍
4.2.1引入依赖
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
</dependency>
</dependencies>
4.2.2 vo基础解析
最基础,直接调
Gson gson = new Gson();
String jsonStr=gson.toJson(vo,JsonVO.class);
/**
* 问题:
* 1.vo对象属性为null不会传递
* 2.日期转化成没有格式化
*
*/
@Test
public void t1(){
Gson gson = new Gson();
JsonVO vo=new JsonVO();
vo.setName("jzk");
vo.setBirth(new Date());
String jsonStr=gson.toJson(vo,JsonVO.class);
System.out.println(jsonStr);
}
效果
{"name":"jzk","birth":"Dec 6, 2023 9:51:56 PM"}
4.2.3 把值为null的传递出去
这里是GsonBuilder来创建Gson对象
Gson gson = new GsonBuilder().serializeNulls().create();
这样获得全部null
@Test
public void t2(){
Gson gson = new GsonBuilder().serializeNulls().create();
JsonVO vo=new JsonVO();
// vo.setName("jzk");
vo.setId(2l);
vo.setBirth(new Date());
String jsonStr=gson.toJson(vo,JsonVO.class);
System.out.println(jsonStr);
}
效果
{
"id":2,"name":null,"weight":null,"birth":"Dec 6, 2023 9:54:19 PM",
"creatTime":null,"money":null,"address":null,
"addresses":null,"son":null,"wifes":null
}
4.2.4 toJson支持对象所有属性转化
public JsonVO getAllVo(){
JsonVO vo=new JsonVO();
vo.setName("jzk");
vo.setBirth(new Date());
vo.setId(1l);
vo.setCreatTime(new Date());
vo.setMoney(true);
vo.setWeight(new BigDecimal("20.56"));
vo.setAddress(new Address("四川","成都"));
List<Address> list=new ArrayList<Address>();
list.add(new Address("四川","绵阳"));
list.add(new Address("四川","简阳"));
vo.setAddresses(list);
Map<String,Object> son=new HashMap<>();
son.put("name","将填好");
son.put("sex","1");
vo.setSon(son);
vo.setWifes(new String[]{"冰冰","雅致"});
return vo;
}
@Test
public void t3(){
Gson gson = new Gson();
JsonVO vo=getAllVo();
String jsonStr=gson.toJson(vo,JsonVO.class);
System.out.println(jsonStr);
}
效果
{
"id":1,"name":"jzk","weight":20.56,"birth":"Dec 6, 2023 9:57:35 PM",
"creatTime":"Dec 6, 2023 9:57:35 PM","money":true,
"address":{"shen":"四川","city":"成都"},
"addresses":
[
{"shen":"四川","city":"绵阳"},{"shen":"四川","city":"简阳"}
],
"son":{"sex":"1","name":"将填好"},
"wifes":["冰冰","雅致"]
}
4.2.5处理null-空值
GsonBuilder.registerTypeAdapter注册,进行重写
帮助类
public class GsonUtil {
public static Gson getGson(){
Gson gson =new GsonBuilder().serializeNulls() //null全部显示
.registerTypeAdapter(String.class,new StringAdapter()) //空字符串处理""
.registerTypeAdapter(Long.class,new LongAdapter()) //Long字段处理成""
.registerTypeAdapter(Integer.class,new IntegerAdapter()) //Integer
.registerTypeAdapter(BigDecimal.class,new BigDecimalAdapter()) //BigDecimal
.registerTypeAdapter(Date.class,new DateAdapter()) //Date
.registerTypeAdapter(Boolean.class,new BooleanAdapter())//Boolean
.create();
return gson;
}
/**
* 字符串为""
*/
public static class StringAdapter extends TypeAdapter<String> {
@Override
public void write(JsonWriter jsonWriter, String s) throws IOException {
if (s == null) {//序列化使用的是adapter的write方法
//jsonWriter.nullValue();//这个方法是错的,而是应该将null转成""
jsonWriter.value("");
return;
}
jsonWriter.value(s);
}
@Override
public String read(JsonReader jsonReader) throws IOException {
if (jsonReader.peek() == JsonToken.NULL) {//反序列化使用的是read方法
jsonReader.nextNull();
return null;
}
return jsonReader.nextString();
}
}
/**
* Long null为""
*/
public static class LongAdapter extends TypeAdapter<Long> {
@Override
public void write(JsonWriter jsonWriter, Long s) throws IOException {
if (s == null) {//序列化使用的是adapter的write方法
//jsonWriter.nullValue();//这个方法是错的,而是应该将null转成""
jsonWriter.value("");
return;
}
jsonWriter.value(s);
}
@Override
public Long read(JsonReader jsonReader) throws IOException {
if (jsonReader.peek() == JsonToken.NULL) {//反序列化使用的是read方法
jsonReader.nextNull();
return null;
}
return jsonReader.nextLong();
}
}
/**
* Double
*/
public static class DoubleAdapter extends TypeAdapter<Double> {
@Override
public void write(JsonWriter jsonWriter, Double s) throws IOException {
if (s == null) {//序列化使用的是adapter的write方法
//jsonWriter.nullValue();//这个方法是错的,而是应该将null转成""
jsonWriter.value("");
return;
}
jsonWriter.value(s);
}
@Override
public Double read(JsonReader jsonReader) throws IOException {
if (jsonReader.peek() == JsonToken.NULL) {//反序列化使用的是read方法
jsonReader.nextNull();
return null;
}
return jsonReader.nextDouble();
}
}
/**
* Boolean
*/
public static class BooleanAdapter extends TypeAdapter<Boolean> {
@Override
public void write(JsonWriter jsonWriter, Boolean s) throws IOException {
if (s == null) {//序列化使用的是adapter的write方法
//jsonWriter.nullValue();//这个方法是错的,而是应该将null转成""
jsonWriter.value("");
return;
}
jsonWriter.value(s);
}
@Override
public Boolean read(JsonReader jsonReader) throws IOException {
if (jsonReader.peek() == JsonToken.NULL) {//反序列化使用的是read方法
jsonReader.nextNull();
return null;
}
return jsonReader.nextBoolean();
}
}
/**
* BigDecimal
*/
public static class BigDecimalAdapter extends TypeAdapter<BigDecimal> {
@Override
public void write(JsonWriter jsonWriter, BigDecimal s) throws IOException {
if (s == null) {//序列化使用的是adapter的write方法
//jsonWriter.nullValue();//这个方法是错的,而是应该将null转成""
jsonWriter.value("");
return;
}
jsonWriter.value(s);
}
@Override
public BigDecimal read(JsonReader jsonReader) throws IOException {
if (jsonReader.peek() == JsonToken.NULL) {//反序列化使用的是read方法
jsonReader.nextNull();
return null;
}
return new BigDecimal(jsonReader.nextString());
}
}
/**
* Integer
*/
public static class IntegerAdapter extends TypeAdapter<Integer> {
@Override
public void write(JsonWriter jsonWriter, Integer s) throws IOException {
if (s == null) {//序列化使用的是adapter的write方法
//jsonWriter.nullValue();//这个方法是错的,而是应该将null转成""
jsonWriter.value("");
return;
}
jsonWriter.value(s);
}
@Override
public Integer read(JsonReader jsonReader) throws IOException {
if (jsonReader.peek() == JsonToken.NULL) {//反序列化使用的是read方法
jsonReader.nextNull();
return null;
}
return jsonReader.nextInt();
}
}
/**
* Integer
*/
public static class DateAdapter extends TypeAdapter<Date> {
@Override
public void write(JsonWriter jsonWriter, Date s) throws IOException {
if (s == null) {//序列化使用的是adapter的write方法
//jsonWriter.nullValue();//这个方法是错的,而是应该将null转成""
jsonWriter.value("");
return;
}
String temp=getStrByDate(s,"yyy-MM-dd HH:mm:ss");
if(temp.indexOf("00:00:00")!=-1){
temp=temp.substring(0,temp.indexOf("00:00:00"));
temp= temp.trim();
}
jsonWriter.value(temp);
}
@Override
public Date read(JsonReader jsonReader) throws IOException {
if (jsonReader.peek() == JsonToken.NULL) {//反序列化使用的是read方法
jsonReader.nextNull();
return null;
}
// return jsonReader.nextString();
System.out.println("jsonReader.nextString()="+jsonReader.nextString());
return getDateByStr(jsonReader.nextString(),"yyy-MM-dd HH:mm:ss");
}
}
private static String getStrByDate(Date date,String gs){
if(date==null)
return "";
DateFormat df = new SimpleDateFormat(gs);
return df.format(date);
}
private static Date getDateByStr(String dateStr,String gs){
if(dateStr==null || dateStr.trim().length()==0)
return null;
DateFormat df = new SimpleDateFormat(gs);
try{
return df.parse(dateStr);
}
catch(ParseException e){
throw new RuntimeException("日期转换出错:"+e);
}
}
}
代码
@Test
public void t4(){
Gson gson= GsonUtil.getGson();
//然后用上面一行写的gson来序列化和反序列化实体类type
JsonVO vo=new JsonVO();
// vo.setName("jzk");
// vo.setId(2l);
//设置一个没有时间的日期
vo.setBirth(DateUtil.getDateByStr("2022-10-01",DateUtil.date_gs));
String jsonStr=gson.toJson(vo,JsonVO.class);
System.out.println(jsonStr);
}
效果
{"id":"","name":"","weight":"","birth":"2022-10-01",
"creatTime":"","money":"","address":null,"addresses":null,
"son":null,"wifes":null,"birth2":null}
4.2.6 日期处理
有三种方式:
1.GsonBuilder…setDateFormat(“yyyy-MM-dd HH:mm:ss”) //设置日期转换
问题:对象里的所有日期只能用一种格式
2.自定义一个类日期属性的注解【如FastJson,Gson没有自带日期注解】
3.做一个TypeAdapter的实现类,自己写(看上文GsonUtil.java里面的代码)
@Test
public void t6(){
//通过setDateFormat来设置日期格式,问题:所有数据都设置成了一种格式
//gson没有提供注解,可以自定义一个注解,处理VO对象里有日期和时间两个字段
Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd HH:mm:ss") //设置日期转换
.create();
JsonVO vo=new JsonVO();
// vo.setName("jzk");
// vo.setId(2l);
vo.setBirth(new Date());
vo.setCreatTime(new Date());
String jsonStr=gson.toJson(vo,JsonVO.class);
System.out.println(jsonStr);
}
效果:
{"birth":"2023-12-06 23:57:12","creatTime":"2023-12-06 23:57:12"}
4.2.7 list和 map处理
gson.toJson(list,ArrayList.class);
gson.toJson(map,HashMap.class);
@Test
public void t33(){
Gson gson = new Gson();
List<Address> list=new ArrayList<Address>();
list.add(new Address("四川","绵阳"));
list.add(new Address("四川","简阳"));
String jsonStr=gson.toJson(list,ArrayList.class);
System.out.println(jsonStr);
Map<String,Object> map=new HashMap();
map.put("name","jzk");
map.put("address","天赋达到");
jsonStr=gson.toJson(map,HashMap.class);
System.out.println(jsonStr);
}
效果
[{"shen":"四川","city":"绵阳"},{"shen":"四川","city":"简阳"}]
{"address":"天赋达到","name":"jzk"}
4.2.8 JSON转java对象
1.json转vo对象
JsonVO vo=new Gson().fromJson(jsonStr,JsonVO.class);
2.json转list< vo >
Type type = new TypeToken<List< Address>>(){}.getType();//获取转化类型
List< Address> list=new Gson().fromJson(json,type)
3.json转map
Map<String,String> map = new Gson().fromJson(json, Map.class);
@Test
public void toVo(){
//有null的数据
String json="{'id':2,'name':null,'weight':null,'birth':'2023-10-23','creatTime':null,'money':null,'address':null,'addresses':null,'son':null,'wifes':null}";
JsonVO vo=new Gson().fromJson(json,JsonVO.class);
System.out.println(vo);
//所有数据都有值
json="{'id':1,'name':'jzk','weight':20.56,'birth':'2021-10-11','creatTime':'2023-10-01 12:23:23','money':true,'address':{'shen':'四川','city':'成都'},'addresses':[{'shen':'四川','city':'绵阳'},{'shen':'四川','city':'简阳'}],'son':{'sex':'1','name':'将填好'},'wifes':['冰冰','雅致']}";
vo =new Gson().fromJson(json,JsonVO.class);
System.out.println(vo);
//json有,vo对象没有字段,不报错
json="{'id':2,'waihao':'黑旋风'}"; //waihao这个属性,vo没有
vo=new Gson().fromJson(json,JsonVO.class);
System.out.println(vo);
//纯List转换
json="[{'shen':'四川','city':'绵阳'},{'shen':'四川','city':'简阳'}]";
Type type = new TypeToken<List<Address>>(){}.getType();//获取转化类型
List<Address> list=new Gson().fromJson(json,type);
for(Address a:list){
System.out.println(a);
}
//map转换
json="{'shen':'四川','city':'绵阳'}";
Map<String,String> map = new Gson().fromJson(json, Map.class);
for(String key:map.keySet()){
String value = map.get(key).toString();
System.out.println("key="+key+" vlaue="+value);
}
}
4.3 Jackson介绍
4.3.1引入依赖
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.1</version>
</dependency>
4.3.2 vo基础解析
String str=new ObjectMapper()…writeValueAsString(解析对象);
问题:
1.全部null都会传递过来
2.时间展示是时间戳格式
@Test
public void t1() throws JsonProcessingException {
JsonVO vo=new JsonVO();
vo.setId(2l);
vo.setBirth(new Date());
ObjectMapper mapper=new ObjectMapper();
String jsonStr="";
jsonStr=mapper.writeValueAsString(vo);
System.out.println(jsonStr);
}
效果
{"id":2,"name":null,"weight":null,"birth":1701912127118,"creatTime":null,
"money":null,"address":null,"addresses":null,"son":null,
"wifes":null,"birth2":null}
4.3.3全局配置
//在反序列化时忽略在 json 中存在但 Java 对象不存在的属性
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
//在序列化时日期格式默认为 yyyy-MM-dd’T’HH:mm:ss.SSSZ
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
//在序列化时自定义时间日期格式
mapper.setDateFormat(new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”));
//在序列化时忽略值为 null 的属性
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
//在序列化时忽略值为默认值的属性
mapper.setDefaultPropertyInclusion(JsonInclude.Include.NON_DEFAULT);
//在反序列时,配置允许单引号,否则json里面的单引号如: ‘name’:'jzk’会报错
mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
//输出json格式化,调试的时候可使用,增加易读性
mapper.writerWithDefaultPrettyPrinter()
4.3.4 支持vo里所有复杂属性的转化
@Test
public void t2()throws JsonProcessingException {
ObjectMapper mapper=new ObjectMapper();
JsonVO vo=getAllVo();
String jsonStr="";
jsonStr=mapper.writerWithDefaultPrettyPrinter().writeValueAsString(vo);
System.out.println(jsonStr);
}
public JsonVO getAllVo(){
JsonVO vo=new JsonVO();
vo.setName("jzk");
vo.setBirth(new Date());
vo.setId(1l);
vo.setCreatTime(new Date());
vo.setMoney(true);
vo.setWeight(new BigDecimal("20.56"));
vo.setAddress(new Address("四川","成都"));
List<Address> list=new ArrayList<Address>();
list.add(new Address("四川","绵阳"));
list.add(new Address("四川","简阳"));
vo.setAddresses(list);
Map<String,Object> son=new HashMap<>();
son.put("name","将填好");
son.put("sex","1");
vo.setSon(son);
vo.setWifes(new String[]{"冰冰","雅致"});
vo.setBirth2(java.sql.Date.valueOf("2012-10-01"));
return vo;
}
效果
{
"id" : 1,
"name" : "jzk",
"weight" : 20.56,
"birth" : 1701917471582,
"creatTime" : 1701917471582,
"money" : true,
"address" : {
"shen" : "四川",
"city" : "成都"
},
"addresses" : [ {
"shen" : "四川",
"city" : "绵阳"
}, {
"shen" : "四川",
"city" : "简阳"
} ],
"son" : {
"sex" : "1",
"name" : "将填好"
},
"wifes" : [ "冰冰", "雅致" ],
"birth2" : 1349020800000
}
4.4.5 把null全部转化成""
重写setNullValueSerializer()方法
@Test
public void t4() throws JsonProcessingException {
ObjectMapper mapper=new ObjectMapper();
mapper.getSerializerProvider().setNullValueSerializer(
new JsonSerializer<Object>() {
@Override
public void serialize(Object paramT,
JsonGenerator paramJsonGenerator, SerializerProvider paramSerializerProvider) throws IOException, JsonProcessingException {
paramJsonGenerator.writeString("");
}
});
JsonVO vo=new JsonVO();
vo.setId(2l);
vo.setBirth(new Date());
String jsonStr="";
jsonStr=mapper.writerWithDefaultPrettyPrinter().writeValueAsString(vo);
System.out.println(jsonStr);
}
效果:
{
"id" : 2,
"name" : "dddddd",
"weight" : "",
"birth" : 1701917789597,
"creatTime" : "",
"money" : "",
"address" : "",
"addresses" : "",
"son" : "",
"wifes" : "",
"birth2" : ""
}
4.4.6日期处理
日期处理有两种方式:
1.在对象属性上配置注解
@JsonFormat(timezone = “GMT+8”, pattern = “yyyy-MM-dd”)
@JsonFormat(timezone = “GMT+8”, pattern = “yyyy-MM-dd HH:mm:ss”)
2.jackson配置类上使用
mapper.setDateFormat(new SimpleDateFormat(“yyyy-MM-dd”));
因为注解大于配置,如果yyyy-MM-dd比较多,setDateFormat配置"yyyy-MM-dd",注解只使用带时分秒的。
省略掉配置日期的注解
代码
vo
ublic class JsonVO {
private Long id;
private String name
private BigDecimal weight;//年纪
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
private Date birth;
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date creatTime;
解析
public void t5() throws JsonProcessingException {
ObjectMapper mapper=new ObjectMapper();
//在序列化时自定义时间日期格式
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));
JsonVO vo=new JsonVO();
vo.setId(2l);
vo.setBirth(new Date());
vo.setBirth2(java.sql.Date.valueOf("2012-12-01"));
vo.setCreatTime(new Date());
String jsonStr="";
jsonStr=mapper.writerWithDefaultPrettyPrinter().writeValueAsString(vo);
System.out.println(jsonStr);
}
效果
{
"id" : 2,
"name" : "dddddd",
"weight" : null,
"birth" : "2023-12-07",
"creatTime" : "2023-12-07 11:54:14",
"money" : null,
"address" : null,
"addresses" : null,
"son" : null,
"wifes" : null,
"birth2" : "2012-12-01"
}
4.4.7 list处理
默认支持list参数
@Test
public void t6() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
List<Address> list=new ArrayList<>();
list.add(new Address("四川","成都"));
list.add(new Address("四川","简阳"));
list.add(new Address());
String jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(list);
System.out.println(jsonInString);
}
效果
[ {
"shen" : "四川",
"city" : "成都"
}, {
"shen" : "四川",
"city" : "简阳"
}, {
"shen" : null,
"city" : null
} ]
4.4.8 map处理
默认支持map
@Test
public void t7() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
Map<String,Object> map=new HashMap<>();
map.put("address","天府大道");
map.put("name","张三丰");
String jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(map);
System.out.println(jsonInString);
}
效果
{
"address" : "天府大道",
"name" : "张三丰"
}
4.3.9 json转vo
注意事项:
1.假如json是单引号 ALLOW_SINGLE_QUOTES=true
2.假如json 中存在但 Java 对象不存在的属性 FAIL_ON_UNKNOWN_PROPERTIES=false
否则前两者要报错
3.json转list和map,需要使用constructCollectionType、constructMapType构造器注意对应的class
@Test
public void t8() throws IOException {
ObjectMapper mapper = new ObjectMapper();
//允许json用单引号,不是双引号
mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
//在反序列化时忽略在 json 中存在但 Java 对象不存在的属性
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
//1.vo部分有值 ok
JsonVO vo=new JsonVO();
String jsonStr="";
jsonStr="{'id':2,'name':'蒋增奎'}";
vo=mapper.readValue(jsonStr,JsonVO.class);
System.out.println(vo);
//2.vo全部有值 ok
jsonStr="{\"id\":1,\"name\":\"jzk\",\"weight\":20.56,\"birth\":\"2023-12-07\",\"creatTime\":\"2023-12-07 13:44:17\",\"money\":true,\"address\":{\"shen\":\"四川\",\"city\":\"成都\"},\"addresses\":[{\"shen\":\"四川\",\"city\":\"绵阳\"},{\"shen\":\"四川\",\"city\":\"简阳\"}],\"son\":{\"sex\":\"1\",\"name\":\"将填好\"},\"wifes\":[\"冰冰\",\"雅致\"],\"birth2\":\"2023-12-07\"}";
vo=mapper.readValue(jsonStr,JsonVO.class);
System.out.println(vo);
//3.json有,但vo里没有对应属性,要使用
// mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
//引号允许
// mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
jsonStr="{'id':2,'name':'蒋增奎','waihao':'带头大哥'}";
vo=mapper.readValue(jsonStr,JsonVO.class);
System.out.println(vo);
//4.直接转化成list
//必须获得一个CollectionType,注入vo.class
CollectionType javaType = mapper.getTypeFactory().constructCollectionType(List.class, Address.class);
jsonStr="[{\"shen\":\"四川\",\"city\":\"成都\"},{\"shen\":\"四川\",\"city\":\"简阳\"},{\"shen\":null,\"city\":null}]";
List<Address> list=mapper.readValue(jsonStr,javaType);
System.out.println("list start -----");
for (Address a:list){
System.out.println(a);
}
//4.直接转化成map
//第二参数是 map 的 key 的类型,第三参数是 map 的 value 的类型
MapType mapJavaType = mapper.getTypeFactory().constructMapType(HashMap.class, String.class, Address.class);
jsonStr="{\"address2\":{\"shen\":\"四川\",\"city\":\"简阳\"},\"address1\":{\"shen\":\"四川\",\"city\":\"成都\"}}";
Map<String,Address> map=mapper.readValue(jsonStr,mapJavaType);
for(String key:map.keySet()){
Address value = map.get(key);
System.out.println("key="+key+" vlaue="+value);
}
}
4.4解析总结
4.5调调用第三方接口json解析
4.5.1 准备工作
Student.java
private Long id;
private String name;
private List<JianLi> jls;
private BigDecimal weight;
private Date birth;
//---------------------------省略get set
}
JianLi.java
public class JianLi {
private Long id;
private String company;
private Date join;
//---------------------------省略get set
}
用一个servlet来发发布json服务接口
@WebServlet(urlPatterns = {"/myjson"})
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
Student student = new Student(12l, "蒋增奎", new BigDecimal("34.56"), Date.valueOf("2001-01-01"));
List<JianLi> list=new ArrayList<>();
list.add(new JianLi(1l,"雪邦科技",new java.util.Date()));
list.add(new JianLi(2l,"朗培教育",new java.util.Date()));
list.add(new JianLi(3l,"众信佳科技",new java.util.Date()));
student.setJls(list);
Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd") //设置日期转换
.create();
String jsonData = gson.toJson(student);
PrintWriter out = response.getWriter();
try {
out.println(jsonData);
} finally {
out.close();
}
}
}
访问http://localhost:8080/web01/myjson,得到如下json
{"id":12,"name":"蒋增奎","weight":34.56,"birth":"2001-01-01",
"jls":
[
{"id":1,"company":"雪邦科技","join":"2023-12-11"},
{"id":2,"company":"朗培教育","join":"2023-12-11"},
{"id":3,"company":"众信佳科技","join":"2023-12-11"}
]
}
4.5.2 javascript客户端访问
用jquey.ajax调用接口
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>json读取</title>
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js">
</script>
<script>
function json() {
$.ajax({
url: "/web01/myjson",
data: {name: 'jenny'},
type: "get",
dataType: "json", //返回的数据类型就是json对象,而不是字符串
success: function(data) {
// data = jQuery.parseJSON(data); //dataType指明了返回数据为json类型,故不需要再反序列化
$("#name").val(data.name);
$("#birth").val(data.birth);
$("#id").val(data.id);
$("#weight").val(data.weight);
//数组
var obj1=data.jls;
var jlsStr="";
for (index in obj1) {
jlsStr+= obj1[index].id + "-" +
obj1[index].company + "-" +
obj1[index].join+"<br>";
}
$("#jls").html(jlsStr);
}
});
}
</script>
</head>
<body>
<input onclick="json()" value="读取json" type="button">
姓名:<input id="name"><br>
ID:<input id="id"><br>
weight:<input id="weight"><br>
birth:<input id="birth"><br>
简历:
<p id="jls"></p>
</body>
</html>
4.5.3 用java访问接口
这个要用到http方面知识,细节参考java网络编程
public class JsonParse {
/**
* 获得一个连接的源码
* @param httpUrl
* @return
*/
public static String doGet(String httpUrl) {
InputStream inputStream = null ;
StringBuffer result = null;
BufferedReader bufferedReader = null ;
HttpURLConnection httpURLConnection = null ;
try {
//初始化URL,传入想访问的地址
URL url = new URL(httpUrl);
//打开URL连接,并新建HttpURLConnection对象
httpURLConnection = (HttpURLConnection)url.openConnection();
//设置请求ban
httpURLConnection.setRequestMethod("GET");
httpURLConnection.setConnectTimeout(15000);
httpURLConnection.setReadTimeout(15000);
result = new StringBuffer() ;
httpURLConnection.connect();
if(httpURLConnection.getResponseCode() == 200) {
inputStream = httpURLConnection.getInputStream();
String inputLine;
if(inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"UTF-8"));
while((inputLine = bufferedReader.readLine()) != null) {
result = result.append(inputLine);
}
}
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e2) {
e2.printStackTrace();
}
}
if(inputStream != null) {
try {
inputStream.close();
} catch (IOException e2) {
e2.printStackTrace();
}
}
httpURLConnection.disconnect();
}
return result.toString();
}
public static void main(String arg[]) {
String resultString = doGet("http://localhost:8080/web01/myjson");
System.out.println(resultString);
Gson gson=new GsonBuilder().setDateFormat("yyyy-MM-dd").create();
Student student=gson.fromJson(resultString,Student.class);
System.out.println(student);
}
}