Java操作json数据

json 简介

概念

  JSON:JavaScript Object Notations,即javaScript的对象表示法,是javaScript语法的一个子集,相当于javaScript中的一个对象。虽然json起源于javaScript,但是很多语言都支持json数据格式的解析与生成,是一种文本数据格式,官方的MIME类型是:application/json
  

应用场景

  1. 常用在使用javaScript,java,node.js开发的web应用中。
  2. 由于json保存的文本数据,因此也用在一些NoSql类型的基于文档类型的数据库中,例如MongoDB.

JSON与XML相比更加轻巧,更易于解析,数据传输更快 。
  
语法格式

   就如前面说的json是javaScript的一个子集,其表现形式就是一个java花括号数据对象,同时json数据格式有着严格的语法要求,一有问题就会解析失败。其语法规则如下:

json中的数据是以键值对的形式存在的,对于键值对有如下要求:

  1. 键和值都需要使用双引号引起来,同时键必须是字符串,值可以是各种javascript类型,或者是另外的json对象
  2. 不同的键值对之间要用逗号隔开,但是要注意最后一个键值对不要使用逗号,不然会报错
  3. 一个json对象需要使用一个花括号来包裹
  4. 值为数组的需要用方括号容纳

json值的类型:

  1. 字符串String
  2. 数字Number
  3. 对象Json
  4. 数组Array
  5. 布尔类型boolean
  6. 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中读取数据

  1. json对象.键名 – person.name = “zhangsan”
  2. json对象[“键名”] – person[“age”] = 21
  3. json对象.数组对象[索引] – person.hobbies[2] = “打机”
  4. 可以使用上述进行嵌套使用 – person.girlFriend.name = “lisi”

  

java操作json数据

   json数据格式可以用于web应用的前后端数据传输中,例如前端发送ajax请求数据。当使用java作为后端的开发语言时,就需要相应的解析,生成json数据的工具类了,下面介绍一款简洁的,快速的json解析工具类:jackson

   jackson可以通过反序列化将前端传递的json对象转成一个java的对象(通常为自定义的一个类实例),也可以将java对象序列化成json对象,传递到前端页面被接收。

  1. 序列化:将java对象转化成字节流数据的过程,
  2. 反序列化:将字节流数据转化成java对象的过程,

注意:json虽然是文本数据格式,但是在网络传输的过程中仍然要转化成字节流数据进行传输。

下面是jackson的使用

2.1导入jar包或依赖

导入jar包

与jackson有关的jar共有三个,分别是:

  1. jackson-annotations.jar – 下载地址:https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
  2. jackson-core.jar – 下载地址:https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
  3. jackson-databind – 下载地址:https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind

进入相应的地址中,点击任意一个版本号之后点击“查看全部”(中文网页),或者“view all”(英文网页),之后界面如下:

javacc 解析js_javacc 解析js

其他两个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字符串并写入到目标源中

  1. writeValue(File file, Objcet obj); – 将obj对象的内容写入File文件中
  2. writeValue(Writer writer, Object obj); – 将obj对象写入到Writer 字符流对象中
  3. 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;
    }
}