• How to use Jackson


    概述

    常有的Java的JSON库有,Jackson、Gson、Fastjson。

    Jackson是一个简单的、功能强大的、基于Java的应用库。它可以很方便完成Java对象Json对象(xml文档or其它格式)进行互转。Jackson社区相对比较活跃,更新速度也比较快。Jackson库有如下几大特性:

    • 高性能且稳定:低内存占用,对大/小JSON串,大/小对象的解析表现均很优秀
    • 流行度高:是很多流行框架的默认选择
    • 容易使用:提供高层次的API,极大简化了日常使用案例
    • 无需自己手动创建映射:内置了绝大部分序列化时和Java类型的映射关系
    • 干净的JSON:创建的JSON具有干净、紧凑、体积小等特点
    • 无三方依赖:仅依赖于JDK
    • Spring生态:jackson是Spring家族的默认JSON/XML解析器

    官方网站

    https://github.com/FasterXML/jackson-docs

    配置

    maven 依赖

    <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.10.0</version>
    </dependency>
    

    ObjectMapper

    com.fasterxml.jackson.databind.ObjectMapper它可以从字符串、流、文件、解析 JSON,并创建表示解析后的 JSON 的 Java 对象。将 JSON 解析为 Java 对象也称为从 JSON 反序列化 Java 对象。

    com.fasterxml.jackson.databind.ObjectMapper还可以从 Java 对象创建 JSON。从 Java 对象生成 JSON 也称为将 Java 对象序列化到 JSON 中。

    JSON to Object

    使用 objectMapper.readValue 可以进行数据绑定, 该方法的重载方法非常多,可以从不同的源中解析绑定 json 对象

    String → Object

    定义一个 vo类, 所有的属性必须有 get set 方法

    public class Car {
        private String brand = null;
        private int doors = 0;
    
        public String getBrand() { return this.brand; }
        public void   setBrand(String brand){ this.brand = brand;}
    
        public int  getDoors() { return this.doors; }
        public void setDoors (int doors) { this.doors = doors; }
    }
    

    使用 ObjectMapper 进行数据绑定

    ObjectMapper objectMapper = new ObjectMapper();
    String carJson = "{ "brand" : "Mercedes", "doors" : 5 }";
    try {
        Car car = objectMapper.readValue(carJson, Car.class);	// 核心方法
        System.out.println("car brand = " + car.getBrand());
        System.out.println("car doors = " + car.getDoors());
    } catch (IOException e) {
        e.printStackTrace();
    }
    

    String[] → Object[]

    String jsonArray = "[{"brand":"ford"}, {"brand":"Fiat"}]";
    ObjectMapper objectMapper = new ObjectMapper();
    Car[] cars2 = objectMapper.readValue(jsonArray, Car[].class);
    

    String[] → List< T>

    String jsonArray = "[{"brand":"ford"}, {"brand":"Fiat"}]";
    ObjectMapper objectMapper = new ObjectMapper();
    List<Car> cars1 = objectMapper.readValue(jsonArray, new TypeReference<List<Car>>(){});
    

    String → Map

    String jsonObject = "{"brand":"ford", "doors":5}";
    ObjectMapper objectMapper = new ObjectMapper();
    Map<String, Object> jsonMap = objectMapper.readValue(jsonObject,new TypeReference<Map<String,Object>>(){});
    

    Reader → Object

    ObjectMapper objectMapper = new ObjectMapper();
    String carJson = "{ "brand" : "Mercedes", "doors" : 4 }";
    Reader reader = new StringReader(carJson);
    Car car = objectMapper.readValue(reader, Car.class);
    

    File → Object

    ObjectMapper objectMapper = new ObjectMapper();
    File file = new File("data/car.json");
    Car car = objectMapper.readValue(file, Car.class);
    

    URL → Object

    ObjectMapper objectMapper = new ObjectMapper();
    URL url = new URL("file:data/car.json");
    Car car = objectMapper.readValue(url, Car.class);
    

    InputStream → Object

    ObjectMapper objectMapper = new ObjectMapper();
    InputStream input = new FileInputStream("data/car.json");
    Car car = objectMapper.readValue(input, Car.class);
    

    byte[] → Object

    ObjectMapper objectMapper = new ObjectMapper();
    String carJson = "{ "brand" : "Mercedes", "doors" : 5 }";
    byte[] bytes = carJson.getBytes("UTF-8");
    Car car = objectMapper.readValue(bytes, Car.class);
    

    一些细节

    设置 JSON 中的空值绑定异常

    如果 JSON 字符串包含一个值设置为 null 的字段,而该字段在相应的 Java 对象中是基元类型(int、 long、 float、 double 等) ,则 Jackson ObjectMapper 可能会失败。

    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, true); // 核心代码
    String carJson = "{ "brand":"Toyota", "doors":null }";
    Car car = objectMapper.readValue(carJson, Car.class);
    

    Object to JSON

    Object → String

    ObjectMapper objectMapper = new ObjectMapper();
    
    Car car = new Car();
    car.brand = "BMW";
    car.doors = 4;
    
    String json = objectMapper.writeValueAsString(car);
    

    JsonParser

    不常用

    com.fasterxml.jackson.core.JsonParser 是一个低级 JSON 解析器,JsonParser 的工作级别低于 Jackson ObjectMapper。这使得 JsonParser 比 ObjectMapper 更快,但使用起来也更麻烦。

    String carJson ="{ "brand" : "Mercedes", "doors" : 5 }";
    
    JsonFactory factory = new JsonFactory();
    JsonParser parser = factory.createParser(carJson);
    

    创建 JsonParser 对象有多种重载方法可用

    JsonParser 解析 JSON

    下面是一个 JsonParser 示例,它简单地循环遍历所有标记并将它们输出到 System.out。这不是一个非常有用的示例,但是它向您展示了 JSON 分解成的标记,并且还向您展示了如何循环遍历标记的基本知识。

    String carJson ="{ "brand" : "Mercedes", "doors" : 5 }";
    
    JsonFactory factory = new JsonFactory();
    JsonParser  parser  = factory.createParser(carJson);
    
    while(!parser.isClosed()){
        JsonToken jsonToken = parser.nextToken();
        System.out.println("jsonToken = " + jsonToken);
    }
    

    使用 JsonParser 的 nextToken ()获得 JsonToken。您可以使用这个 JsonToken 实例来检查给定的令牌。令牌类型由 JsonToken 类中的一组常量表示。这些常数是

    START_OBJECT
    END_OBJECT
    START_ARRAY
    END_ARRAY
    FIELD_NAME
    VALUE_EMBEDDED_OBJECT
    VALUE_FALSE
    VALUE_TRUE
    VALUE_NULL
    VALUE_STRING
    VALUE_NUMBER_INT
    VALUE_NUMBER_FLOAT
    

    可以使用这些常量查找当前 JsonToken 的标记类型。您可以通过这些常量的 equals ()方法来实现。下面是一个例子:

    String carJson = "{ "brand" : "Mercedes", "doors" : 5 }";
    
    JsonFactory factory = new JsonFactory();
    JsonParser  parser  = factory.createParser(carJson);
    
    Car car = new Car();
    while(!parser.isClosed()){
        JsonToken jsonToken = parser.nextToken();		// 核心方法
    
        if(JsonToken.FIELD_NAME.equals(jsonToken)){
            String fieldName = parser.getCurrentName();
            
            System.out.println(fieldName);
            jsonToken = parser.nextToken();
    
            if("brand".equals(fieldName)){
                car.brand = parser.getValueAsString();
            } else if ("doors".equals(fieldName)){
                car.doors = parser.getValueAsInt();
            }
        }
    }
    
    System.out.println("car.brand = " + car.brand);
    System.out.println("car.doors = " + car.doors);
    

    如果指向的令牌是字段名, JsonParser 的 getCurrentName ()方法则返回当前字段名。

    如果指向的令牌是字符串字段值,则 getValueAsString ()以字符串形式返回当前令牌值。如果指向的令牌是整数字段值,则 getValueAsInt ()以 int 形式返回当前令牌值。JsonParser 有更多类似的方法来获取不同类型的 curren 令牌值(例如 boolean、 short、 long、 float、 double 等)。

    JsonGenerator

    com.fasterxml.jackson.core.JsonGenerator 用于从 Java 对象(或者代码中生成 JSON 的任何数据结构) 生成 JSON。

    JsonFactory factory = new JsonFactory();
    JsonGenerator generator = factory.createGenerator(new File("data/output.json"), JsonEncoding.UTF8);
    

    createGenerator ()方法的第一个参数是生成的 JSON 的目标。在上面的示例中,参数是 File 对象。这意味着生成的 JSON 将被写入给定的文件。createGenerator ()方法是重载的,因此 createGenerator ()方法还有其他版本,它接受例如 OutputStream 等,为您提供了将生成的 JSON 写入到哪里的不同选项。

    方法的第二个参数是生成 JSON 时使用的字符编码。上面的示例使用 UTF-8

    有多种方式创建 JsonGenerator

    JsonGenerator 生成 JSON

    创建了 JSON 生成器之后,就可以开始生成 JSON 了。JsonGenerator 包含一组 write... ()方法,您可以使用它们来编写 JSON 对象的各个部分。下面是一个用 Jackson JSON 生成器生成 JSON 的简单示例:

    JsonFactory factory = new JsonFactory();
    
    JsonGenerator generator = factory.createGenerator(
        new File("data/output.json"), JsonEncoding.UTF8);
    
    generator.writeStartObject();
    generator.writeStringField("brand", "Mercedes");
    generator.writeNumberField("doors", 5);
    generator.writeEndObject();
    
    generator.close();
    

    这个示例首先调用 writeStartObject () ,它将{写入输出。然后该示例调用 writeStringField () ,它将 brand 字段 name + value 写入输出。然后调用 writeNumberField ()方法,该方法将 doors 字段 name + value 写入输出。最后,我们调用 writeEndObject () ,它将 a }写入输出。

    关闭 JsonGenerator

    一旦您完成了 JSON 的生成,就应该关闭 JSON 生成器。您可以通过调用它的 close ()方法来实现。下面是关闭 JsonGenerator 的样子:

    generator.close();
    

    关闭 JsonGenerator 还将关闭文件或 OutputStream 等,以便 JsonGenerator 写入生成的 JSON。

    使用场景

    Servlet 接收 JSON 数据并绑定至对象

    前端 axios 发送数据代码

    axios({
        url: rootPath + "/addUser",
        method: 'post',
        data: {
            name: "Haidnor",
            password: "0xeb86d391",
            age: 18
        }
    });
    

    从流中获取数据,自动绑定数据

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        User user = new ObjectMapper().readValue(req.getInputStream(), User.class);
        System.out.println(user);
        // ......
    }
    

    Servlet 发送 JSON 对象数据

        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            // ......
            
            // 从数据库查询对象
            User user = UserDao.selectUserById(10001);
            ObjectMapper objectMapper = new ObjectMapper();
            // 解析对象
            String json = objectMapper.writeValueAsString(user);
            // 发送 json 数据
            resp.getWriter().append(json);
        }
    
  • 相关阅读:
    3164 质因数分解
    codevs3249搭积木
    codevs 2964公共素数因数
    爱改名的小融1
    单链表基础练习
    并查集(union-find sets)
    string类中字符的大小写转换
    蒜头君学英语--set()练习
    打印锯齿矩阵
    堆积木
  • 原文地址:https://www.cnblogs.com/Haidnor/p/13415816.html
Copyright © 2020-2023  润新知