Java操作json数据
json 简介
概念
JSON:JavaScript Object Notations,即javaScript的对象表示法,是javaScript语法的一个子集,相当于javaScript中的一个对象。虽然json起源于javaScript,但是很多语言都支持json数据格式的解析与生成,是一种文本数据格式,官方的MIME类型是:application/json。
应用场景
- 常用在使用javaScript,java,node.js开发的web应用中。
- 由于json保存的文本数据,因此也用在一些NoSql类型的基于文档类型的数据库中,例如MongoDB.
JSON与XML相比更加轻巧,更易于解析,数据传输更快 。
语法格式
就如前面说的json是javaScript的一个子集,其表现形式就是一个java花括号数据对象,同时json数据格式有着严格的语法要求,一有问题就会解析失败。其语法规则如下:
json中的数据是以键值对的形式存在的,对于键值对有如下要求:
- 键和值都需要使用双引号引起来,同时键必须是字符串,值可以是各种javascript类型,或者是另外的json对象
- 不同的键值对之间要用逗号隔开,但是要注意最后一个键值对不要使用逗号,不然会报错
- 一个json对象需要使用一个花括号来包裹
- 值为数组的需要用方括号容纳
json值的类型:
- 字符串String
- 数字Number
- 对象Json
- 数组Array
- 布尔类型boolean
- null
不能为javaScript中undefined,函数,日期类型。
举例
person = {
"name":"zhangsan",
"age":21,
"girlFriend":{"name":"lisi", "age":20},
"hobbies":["跑步", "篮球", "打机"],
"single":false
}
有时候我们从网络中请求的json格式的数据并不会这么规整,这个时候就可以使用json在线解析工具了,将json字符串复制上去即可查看数据的具体轮廓。
注意json数据中是不允许注释的,想要注释需要有其他一些操作,具体原因可上网查。
json字符串
即是将json对象最 外一层的花括号包裹上双引号,在数据传输过程中,常将数据转化为json字符串,然后在解析成json对象。例如
String person = "{
"name":"zhangsan",
"age":21,
"girlFriend":{"name":"lisi", "age":20},
"hobbies":["跑步", "篮球", "打机"],
"single":false
}";
javaScript中读取数据
- json对象.键名 – person.name = “zhangsan”
- json对象[“键名”] – person[“age”] = 21
- json对象.数组对象[索引] – person.hobbies[2] = “打机”
- 可以使用上述进行嵌套使用 – person.girlFriend.name = “lisi”
java操作json数据
json数据格式可以用于web应用的前后端数据传输中,例如前端发送ajax请求数据。当使用java作为后端的开发语言时,就需要相应的解析,生成json数据的工具类了,下面介绍一款简洁的,快速的json解析工具类:jackson。
jackson可以通过反序列化将前端传递的json对象转成一个java的对象(通常为自定义的一个类实例),也可以将java对象序列化成json对象,传递到前端页面被接收。
- 序列化:将java对象转化成字节流数据的过程,
- 反序列化:将字节流数据转化成java对象的过程,
注意:json虽然是文本数据格式,但是在网络传输的过程中仍然要转化成字节流数据进行传输。
下面是jackson的使用
2.1导入jar包或依赖
导入jar包
与jackson有关的jar共有三个,分别是:
- jackson-annotations.jar – 下载地址:https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
- jackson-core.jar – 下载地址:https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
- jackson-databind – 下载地址:https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
进入相应的地址中,点击任意一个版本号之后点击“查看全部”(中文网页),或者“view all”(英文网页),之后界面如下:
其他两个jar包的下载也是一样的。
maven工程中导入
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.11.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.11.2</version>
</dependency>
由于在导入jackson-databind依赖时,另外两个依赖也会同时被导入,因此在项目导入中只导入jackson-databind依赖也是行的。
2.2 java对象转换成json字符串
jackson中用来序列与反序列json数据的类是ObjectMapper(对象映射);在包:com.fasterxml.jackson.databind中。下面举例说明ObjectMapper对象的使用:假设已经创建好了Person的domain对象
1.将java对象转化成一个json格式的字符串
public void test() {
Person p = new Person();
p.setName("张三");
p.setAge(21);
ObjectMapper mapper = new ObjectMapper(); //直接创建该对象即可调用相关方法
String json = mapper.writeValueAsString(p); //即可将p对象转化为json格式的字符串 -- "{"name":"张三", "age":21}"
}
writeValueAsString(Object obj): 可以将一个domain对象转化成相应的json字符串,如果domain中有属性没有值,则会用null替代。很常用!
List集合和Map对象都可以使用该方法,List集合转化的是一个数组嵌套对象的格式,Map对象转化出来的和使用domian对象转化出来的格式是一样的。
2.将java对象转化成json字符串并写入到目标源中
- writeValue(File file, Objcet obj); – 将obj对象的内容写入File文件中
- writeValue(Writer writer, Object obj); – 将obj对象写入到Writer 字符流对象中
- writeValue(OutputStream output, Object obj); – 将obj对象写入OutputStream 字节流对象中
public void test() {
Person p = new Person();
p.setName("张三");
p.setAge(21);
ObjectMapper mapper = new ObjectMapper(); //直接创建该对象即可调用相关方法
mapper.writeValue(new File("D://test.txt"), p); //将p对象写入File对象
mapper.writeValue(new FileWrite("D://test1.txt"), p);
mapper.writeValue(new FileOutputStream(new File("D://test2.txt")), p);
}
2.3 jackson相关的注解
- 上面提到了在将java对象转化成ObjectMapper对象时,如果相关的属性没有值则会转化成null,如果我们不需要相关的属性,即可在定义属性的语句上面加上下面注解:
@JsonIgnore
例如:
@JsonIgnore
private int money;
这样在转化为json字符串对象的时候就不会讲该属性转化上了。
- 对于时间属性的转化,可以使用下面注解
@JsonFormat(pattern = “yyyy-MM-dd”)
private Date birthday;
这样显示的时间格式就是:2020-09-30,如果不使用上面注解的话,显示的就是对应时间的时间戳。
2.4 json转化为java对象
通过ObjectMapper方法将json字符串转化为java的domain对象也是行的,但是用得并不多,具体使用方式如下:
public void test() {
ObjectMapper mapper = new ObjectMapper(); //直接创建该对象即可调用相关方法
String json = "{"name":"张三", "age":21}";
Person person = mapper.readValue(json, Person.class); //可将json字符串转化为Person对象
}
这种方式并没有那么常用。
前后端数据交互举例
模拟用户登录,判断用户输入的用户名和密码是否匹配,验证码是否正确,错误则返回相应的提示信息,其中ResultInfo对象是一个domian对象,用来保存相应的错误信息的。
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Map<String, String[]> map = request.getParameterMap();
ResultInfo info = new ResultInfo();
ObjectMapper mapper = new ObjectMapper(); //创建ObjectMapper对象
//获取验证码
HttpSession session = request.getSession();
String checkcode_server = (String)session.getAttribute("CHECKCODE_SERVER");
session.removeAttribute("CHECKCODE_SERVER");
String checkcode = request.getParameter("check");
if (!checkcode.equalsIgnoreCase(checkcode_server)) {
info.setFlag(false);
info.setErrorMsg("验证码错误");
String json = mapper.writeValueAsString(info); //将对象转化成json字符串
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(json); //将对象写会前端
return ;
} else {
User user = new User();
try {
BeanUtils.populate(user, map);
//将用户信息保留在session中
session.setAttribute("user", user);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
UserService service = new UserServiceImpl();
boolean status = service.login(user);
if (status) {
if (!service.hasCertification(user)) {
info.setFlag(false);
info.setErrorMsg("邮箱还没有认证,请查看您的邮箱进行认证!");
} else {
info.setFlag(true);
}
} else {
info.setFlag(false);
info.setErrorMsg("账号或密码错误");
}
String json = mapper.writeValueAsString(info); //将对象转化成json字符串
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(json); //将对象写会前端
}
}
ResultInfo类:
package cn.itcast.travel.domain;
import java.io.Serializable;
import java.util.Objects;
/**
* 1.用于封装后端返回前端数据对象
* 2.同时判断返回的数据是否有误
* 3.记录其发生异常的信息 -- 注意这里是用来展示到前台上的错误信息
*/
public class ResultInfo implements Serializable {
/**
* true: 后端返回结果正常
* false:后端返回结果错误
*/
private boolean flag;
/**
* 后端返回结果的数据对象
*/
private Object data;
/**
* 发生异常的错误信息
*/
private String errorMsg;
public ResultInfo() {}
/**
* 带参构造
* @param flag
*/
public ResultInfo(boolean flag) {
this.flag = flag;
}
/**
* 有参构造方法
* @param flag
* @param errorMsg
*/
public ResultInfo(boolean flag, String errorMsg) {
this.flag = flag;
this.errorMsg = errorMsg;
}
/**
* 有参构造方法
* @param flag
* @param data
* @param errorMsg
*/
public ResultInfo(boolean flag, Object data, String errorMsg) {
this.flag = flag;
this.data = data;
this.errorMsg = errorMsg;
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public String getErrorMsg() {
return errorMsg;
}
public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
}
}