Java中JSON字符串与Java对象之间的转换

1、Java与前台的交互

  • 作为后台,Java不仅需要接收前台传递过来的数据,还需要将数据库中的数据查出来打包好发给前台,无论是接收还是发送的数据,都是以JSON字符串的形式存在的;
  • JSON数据详解
  • 我们在发送JSON字符串的时候,可以选择手动拼串,但是这样显然很繁琐,同样,接收前台返回来的JSON字符串,解析该字符串也会显得很繁琐;
  • 我们可以使用一些第三方的工具类进行处理;

常见的JSON解析器:

Jsonlib,Gson,fastjson,jackson;

2、解析JSON的第三方工具

  • Gson

Gson是目前功能最全的Json解析神器,它当初是为因应Google公司内部需求而由Google自行研发而来,但自从在2008年五月公开发布第一版后已被许多公司或用户应用。 Gson的应用主要为toJson与fromJson两个转换函数,无依赖,不需要例外额外的jar,能够直接跑在JDK上。 在使用这种对象转换之前,需先创建好对象的类型以及其成员才能成功的将JSON字符串成功转换成相对应的对象。 类里面只要有get和set方法,Gson完全可以实现复杂类型的json到bean或bean到json的转换,是JSON解析的神器。

  • FastJson

Fastjson是一个Java语言编写的高性能的JSON处理器,由阿里巴巴公司开发。无依赖,不需要例外额外的jar,能够直接跑在JDK上。 FastJson在复杂类型的Bean转换Json上会出现一些问题,可能会出现引用的类型,导致Json转换出错,需要制定引用。 FastJson采用独创的算法,将parse的速度提升到极致,超过所有json库。

  • Jackson

项目地址

Jackson是当前用的比较广泛的,用来序列化和反序列化json的Java开源框架。Jackson社区相对比较活跃,更新速度也比较快, 从Github中的统计来看,Jackson是最流行的json解析器之一,Spring MVC的默认json解析器便是Jackson。

Jackson优点很多:

  • Jackson 所依赖的jar包较少,简单易用;
  • 与其他 Java 的 json 的框架 Gson 等相比,Jackson 解析大的 json 文件速度比较快;
  • Jackson 运行时占用内存比较低,性能比较好;
  • Jackson 有灵活的 API,可以很容易进行扩展和定制。
  • Jackson 的核心模块由三部分组成:
    在这里插入图片描述

jackson-core 核心包 提供基于"流模式"解析的相关 API,它包括JsonPaserJsonGenerator。Jackson 内部实现正是通过高性能的流模式 API 的 JsonGenerator 和 JsonParser 来生成和解析 json。
jackson-annotations注解包,提供标准注解功能;
jackson-databind 数据绑定包,提供基于"对象绑定" 解析的相关 API( ObjectMapper )和"树模型" 解析的相关 API(JsonNode);基于"对象绑定" 解析的 API 和"树模型"解析的 API 依赖基于"流模式"解析的 API。

  • Json-lib

json-lib最开始的也是应用最广泛的json解析工具,json-lib 不好的地方确实是依赖于很多第三方包,对于复杂类型的转换,json-lib对于json转换成bean还有缺陷, 比如一个类里面会出现另一个类的list或者map集合,json-lib从json到bean的转换就会出现问题。json-lib在功能和性能上面都不能满足现在互联网化的需求。

3、JSON数据和Java对象的相互转换

Java对象转换JSON字符串

  • 使用步骤:

1、导入jackson的相关jar包
2、创建Jackson核心对象 ObjectMapper
3、调用ObjectMapper的相关方法进行转换

单个对象转为JSON字符串

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class MyTest {
    public static void main(String[] args) throws JsonProcessingException {
        Phone phone = new Phone();
        phone.setName("小米");
        phone.setColor("红色");
        phone.setPrice(2000);

        ObjectMapper mapper = new ObjectMapper();
        String value = mapper.writeValueAsString(phone);
        System.out.println(value);
        //{"name":"小米","color":"红色","price":2000}
    }
}

writeValueAsString(obj)——将对象转为json字符串

将对象放入单列集合转为JSON字符串

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.ArrayList;

public class MyTest1 {
    public static void main(String[] args) throws JsonProcessingException {
        Phone phone = new Phone();
        phone.setName("小米");
        phone.setColor("红色");
        phone.setPrice(2000);

        Phone phone1 = new Phone();
        phone1.setName("华为");
        phone1.setColor("红色");
        phone1.setPrice(1000);

        Phone phone2 = new Phone();
        phone2.setName("苹果");
        phone2.setColor("黑色");
        phone2.setPrice(3000);

        ArrayList<Phone> list = new ArrayList<>();
        list.add(phone);
        list.add(phone1);
        list.add(phone2);

        ObjectMapper mapper = new ObjectMapper();
        String value = mapper.writeValueAsString(list);
//        [{"name":"小米","color":"红色","price":2000},{"name":"华为","color":"红色","price":1000},{"name":"苹果","color":"黑色","price":3000}]  数组的形式
        System.out.println(value);
    }
}

可以看到最终转换出来的结果是JSON数组格式;

将对象放入双列集合转为JSON字符串

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.HashMap;

public class MyTest2 {
    public static void main(String[] args) throws JsonProcessingException {
        Phone phone = new Phone();
        phone.setName("小米");
        phone.setColor("红色");
        phone.setPrice(2000);

        Phone phone1 = new Phone();
        phone1.setName("华为");
        phone1.setColor("红色");
        phone1.setPrice(1000);

        Phone phone2 = new Phone();
        phone2.setName("苹果");
        phone2.setColor("黑色");
        phone2.setPrice(3000);

        HashMap<String, Phone> map = new HashMap<>();
        map.put("phone1",phone);
        map.put("phone2",phone1);
        map.put("phone3",phone2);

        ObjectMapper mapper = new ObjectMapper();
        String value = mapper.writeValueAsString(map);
        System.out.println(value);
//        {"phone2":{"name":"华为","color":"红色","price":1000},"phone3":{"name":"苹果","color":"黑色","price":3000},"phone1":{"name":"小米","color":"红色","price":2000}}

    }
}

可以看到最终转换的结果是JSON嵌套的格式;

一个对象内部维护了另外一个对象转为JSON字符串

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.HashMap;

public class MyTest3 {
    public static void main(String[] args) throws JsonProcessingException {
        Phone phone = new Phone();
        phone.setName("小米");
        phone.setColor("红色");
        phone.setPrice(2000);
        phone.setBox(new Phone.PhoneBox("手机壳1","red"));

        Phone phone1 = new Phone();
        phone1.setName("华为");
        phone1.setColor("白色");
        phone1.setPrice(1000);
        phone1.setBox(new Phone.PhoneBox("手机壳2","white"));

        Phone phone2 = new Phone();
        phone2.setName("苹果");
        phone2.setColor("黑色");
        phone2.setPrice(3000);
        phone2.setBox(new Phone.PhoneBox("手机壳3","black"));

        HashMap<String, Phone> map = new HashMap<>();
        map.put("phone1",phone);
        map.put("phone2",phone1);
        map.put("phone3",phone2);

        ObjectMapper mapper = new ObjectMapper();
        String str = mapper.writeValueAsString(map);
        System.out.println(str);
//        {"phone2":{"name":"华为","color":"白色","price":1000,"box":{"boxName":"手机壳2","boxColor":"white"}},"phone3":{"name":"苹果","color":"黑色","price":3000,"box":{"boxName":"手机壳3","boxColor":"black"}},"phone1":{"name":"小米","color":"红色","price":2000,"box":{"boxName":"手机壳1","boxColor":"red"}}}
        //类似于套娃的格式
    }
}

静态内部类的代码:

public class Phone {
    private String name;
    private String color;
    private int price;
    private PhoneBox box;
	……
    static class PhoneBox{
        private String boxName;
        private String boxColor;
		……
    }
}

可以看到,一个对象内部维护了另外一个对象的时候,任然可以转换为字符串,这时候的格式就类似于套娃;
一般我们将这个内部的类写为静态的内部类;

嵌套类详解

将转换过来的JSON字符串存入文本当中

writeValue(参数1,obj):
参数1:
File:将obj对象转换为JSON字符串,并保存到指定的文件中
Writer:将obj对象转换为JSON字符串,并将json数据填充到字符输出流中
OutputStream:将obj对象转换为JSON字符串,并将json数据填充到字节输出流中

import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;

public class MyTest4 {
    public static void main(String[] args) throws IOException {
        //writeValue
        Phone phone = new Phone();
        phone.setName("小米");
        phone.setColor("红色");
        phone.setPrice(2000);
        phone.setBox(new Phone.PhoneBox("手机壳1","red"));

        Phone phone1 = new Phone();
        phone1.setName("华为");
        phone1.setColor("白色");
        phone1.setPrice(1000);
        phone1.setBox(new Phone.PhoneBox("手机壳2","white"));

        Phone phone2 = new Phone();
        phone2.setName("苹果");
        phone2.setColor("黑色");
        phone2.setPrice(3000);
        phone2.setBox(new Phone.PhoneBox("手机壳3","black"));

        HashMap<String, Phone> map = new HashMap<>();
        map.put("phone1",phone);
        map.put("phone2",phone1);
        map.put("phone3",phone2);

        ObjectMapper mapper = new ObjectMapper();
        mapper.writeValue(new File("a.json"),map);
        mapper.writeValue(new FileOutputStream("b.json"),map);
        mapper.writeValue(new FileWriter("c.json"),map);
    }
}

在这里插入图片描述
选择部分属性转为JSON字符串

  • 有的时候,我们只想转换部分数据返回给前台,并不想返回后台的全部数据,可以使用注解:

1、@JsonIgnore:排除某个属性不要转换成JSON,给类的属性上加上这个注解。
2、@JsonFormat:属性值得格式化日期字符串,取的是默认时区的时间

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.ArrayList;

public class MyTest5 {
    public static void main(String[] args) throws JsonProcessingException {
        Phone phone = new Phone();
        phone.setName("小米");
        phone.setColor("红色");
        phone.setPrice(2000);
        phone.setBox(new Phone.PhoneBox("手机壳1","red"));

        Phone phone1 = new Phone();
        phone1.setName("华为");
        phone1.setColor("白色");
        phone1.setPrice(1000);
        phone1.setBox(new Phone.PhoneBox("手机壳2","white"));

        Phone phone2 = new Phone();
        phone2.setName("苹果");
        phone2.setColor("黑色");
        phone2.setPrice(3000);
        phone2.setBox(new Phone.PhoneBox("手机壳3","black"));

        ArrayList<Phone> list = new ArrayList<>();
        list.add(phone);
        list.add(phone1);
        list.add(phone2);

        ObjectMapper mapper = new ObjectMapper();
        String value = mapper.writeValueAsString(list);
        System.out.println(value);
//        {"name":"小米","color":"红色","box":{"boxName":"手机壳1"}},{"name":"华为","color":"白色","box":{"boxName":"手机壳2"}},{"name":"苹果","color":"黑色","box":{"boxName":"手机壳3"}}]
    }
}

自定义类:

public class Phone {
    private String name;
    private String color;
    @JsonIgnore
    private int price;
    private PhoneBox box;
    ……

    static class PhoneBox{
        private String boxName;
        @JsonIgnore
        private String boxColor;
        ……
    }
}

get()和set(0不能省略,因为转换为JSON字符串的内部会用到这两个方法;

添加注解解析日期类的属性值

没有添加注解@JsonFormat之前:

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class MyTest6 {
    public static void main(String[] args) throws ParseException, JsonProcessingException {
        String strBir1="2000-09-10";
        Date date1 = new SimpleDateFormat("yyyy-MM-dd").parse(strBir1);
        String strBir2="2001-09-01";
        Date date2= new SimpleDateFormat("yyyy-MM-dd").parse(strBir2);
        String strBir3="2002-11-10";
        Date date3= new SimpleDateFormat("yyyy-MM-dd").parse(strBir3);
        Person person1 = new Person("张三", 23, date1);
        Person person2 = new Person("李四",24,date2);
        Person person3 = new Person("王五",25,date3);

        ObjectMapper mapper = new ObjectMapper();
        String str1 = mapper.writeValueAsString(person1);
        System.out.println(str1);
        String str2 = mapper.writeValueAsString(person2);
        System.out.println(str2);
        String str3 = mapper.writeValueAsString(person3);
        System.out.println(str3);
        /*{"name":"张三","age":23,"birthday":968515200000}
        {"name":"李四","age":24,"birthday":999273600000}
        {"name":"王五","age":25,"birthday":1036857600000}*/
    }
}

添加完@JsonFormat注解之后:

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class MyTest6 {
    public static void main(String[] args) throws ParseException, JsonProcessingException {
        String strBir1="2000-09-10";
        Date date1 = new SimpleDateFormat("yyyy-MM-dd").parse(strBir1);
        String strBir2="2001-09-01";
        Date date2= new SimpleDateFormat("yyyy-MM-dd").parse(strBir2);
        String strBir3="2002-11-10";
        Date date3= new SimpleDateFormat("yyyy-MM-dd").parse(strBir3);
        Person person1 = new Person("张三", 23, date1);
        Person person2 = new Person("李四",24,date2);
        Person person3 = new Person("王五",25,date3);

        ObjectMapper mapper = new ObjectMapper();
        String str1 = mapper.writeValueAsString(person1);
        System.out.println(str1);
        String str2 = mapper.writeValueAsString(person2);
        System.out.println(str2);
        String str3 = mapper.writeValueAsString(person3);
        System.out.println(str3);
        /*{"name":"张三","age":23,"birthday":"2000-09-10 00:00:00"}
        {"name":"李四","age":24,"birthday":"2001-09-01 00:00:00"}
        {"name":"王五","age":25,"birthday":"2002-11-10 00:00:00"}*/
    }
}

自定义类中的代码:

public class Person {
    private String name;
    private int age;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    //给默认时区加上8个小时
    private Date birthday;
}

JSON字符串转为Java对象

1、导入jackson的相关jar包;
2、创建Jackson核心对象 ObjectMapper;
3、调用ObjectMapper的相关方法进行转换
4、readValue(json字符串数据,Class)

  • 把JSON字符串,转换成JSON对象,前提是 需要提供一个类,这个类的属性名和JSON字符串中的键名保持一致;
import java.io.IOException;

public class MyTest {
    public static void main(String[] args) throws IOException {
        String jsonStr = "{\"name\":\"张三\",\"age\":23,\"sex\":\"男\"}";
        ObjectMapper mapper = new ObjectMapper();
        Student student = mapper.readValue(jsonStr, Student.class);
        System.out.println(student);
        //Student{name='张三', age=23, sex='男'}
    }
}
public class Student {
    private String name;
    private int age;
    private String sex;
	…………
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                '}';
    }
}

JSON嵌套的解析

public class MyTest2 {
    public static void main(String[] args) throws IOException {
        String jsonStr = "{\"name\":\"小米\",\"color\":\"白色\",\"price\":800,\"date\":null,\"phoneBox\":{\"boxName\":\"手机壳\",\"boxColor\":\"透明\"}}";
        ObjectMapper mapper = new ObjectMapper();
        Phone value = mapper.readValue(jsonStr, Phone.class);
        System.out.println(value);
        //Phone{color='白色', date=null, name='小米', phoneBox=PhoneBoxBean{boxColor='透明', boxName='手机壳'}, price=800}
    }
}
public class Phone {
    private String color;
    private Date date;
    private String name;
    private PhoneBoxBean phoneBox;
    private int price;
    ……

    public static class PhoneBoxBean {
        private String boxColor;
        private String boxName;
        ……
    }
}

GSONFormat插件

  • 有的时候我们需要解析的JSON字符串较为简单,可以自己定义实现类,但有的时候字符串非常复杂,这时候IDEA给我们提供了一款插件:GSONFormat,安装好这款插件之后,在Generate中找到它:
    在这里插入图片描述
    在这里插入图片描述
    v

上图是软件帮我们自动生成的属性;使用这个插件,简化了我们的代码量;

©️2020 CSDN 皮肤主题: 精致技术 设计师:CSDN官方博客 返回首页