• JSON操作


    一、JSON简介

    JSON: JavaScript Object Notation(JavaScript 对象表示法)

    JSON 是存储和交换文本信息的语法。类似 XML。

    JSON 比 XML 更小、更快,更易解析。

    JSON 使用 Javascript语法来描述数据对象,但是 JSON 仍然独立于语言和平台。JSON 解析器和 JSON 库支持许多不同的编程语言。 目前非常多的动态(PHP,JSP,.NET)编程语言都支持JSON。

    1. JSON语法
    JSON 语法规则
    • 数据在名称/值对中
    • 数据由逗号分隔
    • 花括号保存对象
    • 方括号保存数组
    JSON 名称/值对

    JSON 数据的书写格式是:名称/值对。

    名称/值对包括字段名称(在双引号中),后面写一个冒号,然后是值:

    “name” : “zhangsan”

    这很容易理解,等价于这条 JavaScript 语句:

    name = "zhangsan"
    JSON 值类型

    JSON 值可以是:

    • 字符串(在双引号中)
    • 数字(整数或浮点数)
    • 对象(在花括号中)
    • 数组(在方括号中)
    • 逻辑值(true 或 false)
    • Null
    2. JSON的数据结构

    JSON有两种数据结构:对象和数组。

    JSON对象

    对象是一个无序的“‘名称/值’对”集合(A collection of name/value pairs)。不同的语言中,它被理解为对象(object),纪录(record),结构(struct),字典(dictionary),哈希表(hash table),有键列表(keyed list),或者关联数组 (associative array)。

    一个对象以“{”(左括号)开始,“}”(右括号)结束。每个“名称”后跟一个“:”(冒号);“‘名称/值’ 对”之间使用“,”(逗号)分隔。

    JSON 对象在花括号中书写:

    { "name":"zhangsan" , "age":24 }

    这一点也容易理解,与这条 JavaScript 语句等价:

    name = "zhangsan"
    age = 24
    JSON数组

    值的有序列表(An ordered list of values)。在大部分语言中,它被理解为数组(array)。

    JSON 数组在方括号中书写:

    数组可包含多个对象:

    {
             "people": [
                       { "namr":"zhangsan" , "age":22 },
                       { "name":"lisi" , "age":24 },
                       { "name":"wangwu" , "age":27 }
             ]
    }

    在上面的例子中,对象 "employees" 是包含三个对象的数组。每个对象代表一条关于某人(有姓和名)的记录。

    二、Java 中操作 JSON 数据

    网上有很多JAVA种操作JSON的jar包,比较流行的类库Jackson、Gson和FastJSON。

    注意:在Maven的中的引用量,FastJSON和Jackson和Gson不在一个数量级,据说是一个代码质量不高的国产类库,还是存在较多的问题的。

    这里就介绍下Jackson和Gson。

    1. Jackson

    Jackson提供了三种可选的JSON处理方法:

    流式API

    com.fasterxml.jackson.core.JsonParser读 -- 通过JsonFactory构建
    com.fasterxml.jackson.core.JsonGenerator写 -- 通过JsonFactory构建

    树模型:提供一个 JSON 文档可变内存树的表示形式 

    com.fasterxml.jackson.databind.ObjectMapper生成树 ;树组成 JsonNode 节点集
    树模型类似于 XML DOM。

    数据绑定:JSON和POJO相互转换,基于属性访问器规约或注解

    有两种变体:简单和完整的数据绑定

    • 简单数据绑定:是指从Java Map、List、String、Numbers、Boolean和空值进行转换
    • 完整数据绑定:是指从任何Java bean 类型(及上文所述的"简单"类型)进行转换

    com.fasterxml.jackson.databind.ObjectMapper对两个变种进行编排(marshalling)处理(写入JSON)和反编排(unmarshalling读JSON)。

    3 种方法的用法如下 

    • 流 API: 性能最佳的方式 (最低开销、 速度最快的读/写; 其它二者基于它实现)。
    • 数据绑定 :使用最方便的方式。
    • 树模型: 最灵活的方式。
    添加依赖
    <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.11.0</version>
    </dependency>
    流API

    使用JsonGenerator写入JSON

    写入对象

    JsonFactory factory = new JsonFactory();
    //JsonGenerator 定义公共API编写的Json内容的基类。使用JsonFactory实例的工厂方法创建实例(createGenerator)。
    JsonGenerator jsonGenerator = factory.createGenerator(new File("D:\idea_workspace\springboot\ComJava\src\main\resources\student.json"), JsonEncoding.UTF8);
    // {
    jsonGenerator.writeStartObject();
    // "name" : "harvey"
    jsonGenerator.writeStringField("name", "harvey");
    // "age" : 20
    jsonGenerator.writeNumberField("age", 20);
    // "isMan" : false
    jsonGenerator.writeBooleanField("isMan", false);
    // "marks" : [20, 5, 40]
    jsonGenerator.writeFieldName("marks");
    // [
    jsonGenerator.writeStartArray();
    //20, 5, 40
    jsonGenerator.writeNumber(20);
    jsonGenerator.writeNumber(5);
    jsonGenerator.writeNumber(40);
    // ]
    jsonGenerator.writeEndArray();
    // }
    jsonGenerator.writeEndObject();
    jsonGenerator.close();

    写入数组

    JsonFactory factory = new JsonFactory();
    //JsonGenerator 定义公共API编写的Json内容的基类。使用JsonFactory实例的工厂方法创建实例(createGenerator)。
    JsonGenerator jsonGenerator = factory.createGenerator(new File("D:\idea_workspace\springboot\ComJava\src\main\resources\student.json"), JsonEncoding.UTF8);
    // {
    jsonGenerator.writeStartObject();;
    // "students": []
    jsonGenerator.writeFieldName("students");
    // [
    jsonGenerator.writeStartArray();
    //如果有多个对象,这里循环即可
    // {
    jsonGenerator.writeStartObject();;
    // "name" : "harvey"
    jsonGenerator.writeStringField("name", "harvey");
    // "age" : 20
    jsonGenerator.writeNumberField("age", 20);
    // "isMan" : false
    jsonGenerator.writeBooleanField("isMan", false);
    // }
    jsonGenerator.writeEndObject();;
    // ]
    jsonGenerator.writeEndArray();
    // }
    jsonGenerator.writeEndObject();;
    jsonGenerator.close();

    使用JsonParser 读取JSON

    JsonFactory factory = new JsonFactory();
    //JsonParser 定义公共API用于读取的Json内容的基类。使用JsonFactory实例的工厂方法创建实例(createParser)。
    JsonParser jsonParser = factory.createParser(new File("D:\idea_workspace\springboot\ComJava\src\main\resources\student.json"));
    while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
        //get the current token
        String fieldName = jsonParser.getCurrentName();
        if ("name".equals(fieldName)) {
            //move to next token
            jsonParser.nextToken();
            System.out.println(jsonParser.getText());
        }
        if("age".equals(fieldName)){
            //move to next token
            jsonParser.nextToken();
            System.out.println(jsonParser.getNumberValue());
        }
        if("isMan".equals(fieldName)){
            //move to next token
            jsonParser.nextToken();
            System.out.println(jsonParser.getBooleanValue());
        }
        if("marks".equals(fieldName)){
            //move to [
            jsonParser.nextToken();
            // loop till token equal to "]"
            while (jsonParser.nextToken() != JsonToken.END_ARRAY) {
                System.out.println(jsonParser.getNumberValue());
            }
        }
    }
    树模型

    树到JSON转换

    ObjectMapper mapper = new ObjectMapper();
    String jsonString = "{"name":"Mahesh Kumar", "age":21,"verified":false,"marks": [100,90,85]}";
    JsonNode rootNode = mapper.readTree(jsonString);
    
    JsonNode nameNode = rootNode.path("name");
    System.out.println("Name: "+ nameNode.asText());
    
    JsonNode ageNode = rootNode.path("age");
    System.out.println("Age: " + ageNode.asInt());
    
    JsonNode verifiedNode = rootNode.path("verified");
    System.out.println("Verified: " + (verifiedNode.asBoolean() ? "Yes":"No"));
    
    JsonNode marksNode = rootNode.path("marks");
    Iterator<JsonNode> iterator = marksNode.iterator();
    System.out.print("Marks: [ ");
    while (iterator.hasNext()) {
        JsonNode marks = iterator.next();
        System.out.print(marks.asInt() + " ");
    }
    System.out.println("]");
    数据绑定

    通常都是json字符串与对象的相互转换。

    ObjectMapper convertMapper = new ObjectMapper();
    //对象转json
    convertMapper.writeValueAsString(Object value);
    //json转对象
    convertMapper.readValue(String content, Class<T> valueType)
    对象序列化
    Student student = new Student();
    student.setAge(10);
    student.setName("Harvey");
    
    //对象序列化
    ObjectMapper mapper = new ObjectMapper();
    //示例一
    mapper.writeValue(new File("D:\idea_workspace\springboot\ComJava\src\main\resources\student.json"), student);
    // 还有其他形式
    // void writeValue(OutputStream out, Object value)
    // void writeValue(Writer w, Object value)
    // String writeValueAsString(Object value)
    // byte[] writeValueAsBytes(Object value)
    
    //示例二
    Student readStudent = mapper.readValue(new File("D:\idea_workspace\springboot\ComJava\src\main\resources\student.json"), Student.class);
    System.out.println(readStudent.getName());
    // 还有其他形式
    // <T> T readValue(String content, Class<T> valueType)
    // <T> T readValue(byte[] src, Class<T> valueType)
    
    
    //实体类
    class Student {
        private String name;
        private int age;
        public Student(){}
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public String toString(){
            return "Student [ name: "+name+", age: "+ age+ " ]";
        }
    }
    2. Gson
    添加依赖
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.8.6</version>
    </dependency>
    gson实例化的两种方式

    第一种

    Gson gson  = new Gson();

    第二种

    Gson gson = new GsonBuilder()
                .setLenient()// json宽松
                .enableComplexMapKeySerialization()//支持Map的key为复杂对象的形式
                .serializeNulls() //智能null
                .setPrettyPrinting()// 调教格式
                .disableHtmlEscaping() //默认是GSON把HTML转义的
                .create();
    Bean、Map、List的相互转换

    Gson提供了fromJson() 和toJson() 两个直接用于解析和生成的方法,前者实现反序列化,后者实现了序列化;同时每个方法都提供了重载方法。

    Gson的注解

    注:在Gson中有5类注解 。

    @SerializedName注解(JSON字段重命名)

    该注解能指定该字段在JSON中对应的字段名称,就是将POJO中的字段与JSON字符串中的字段对应起来。
    输出的json使用另外一个名字,默认转换出来的json中和对象的字段是一样的,当然也可以设置成不同,使用SerializedName 注解 。

    @Expose注解(字段过滤)

    指定哪些是要暴露转换的属性。有时候我们不需要把实体的所有属性都导出,只想把一部分属性导出为Json,或只想对一部分POJO的字段进行反序列化。

    @Since(double v) 与 @Until(double v)注解 (版本控制)

    有时候我们的实体类会随着版本的升级而修改。一些新的字段是后续加进来的,在新的版本软件中才使用。

    JsonAdapter注解 (使用TypeAdapter时的注解)

    参考

    https://www.cnblogs.com/jingmoxukong/p/4664224.html

  • 相关阅读:
    20165226 2017-2018-4 《Java程序设计》第8周学习总结
    20165226第二次实验
    结对编程练习-四则运算(第一周)
    20165226 2017-2018-4 《Java程序设计》第7周学习总结
    20165226 2017-2018-4 《Java程序设计》第6周学习总结
    实验一 Java开发环境的熟悉
    20165226 2017-2018-3 《Java程序设计》第5学习总结
    第四周课下作业
    第4周学习总结
    第三周学习
  • 原文地址:https://www.cnblogs.com/myitnews/p/12952615.html
Copyright © 2020-2023  润新知