【25】Json解析

(1)一个人只要自己不放弃自己,整个世界也不会放弃你.
(2)天生我才必有大用
(3)不能忍受学习之苦就一定要忍受生活之苦,这是多么痛苦而深刻的领悟.
(4)做难事必有所得
(5)精神乃真正的刀锋
(6)战胜对手有两次,第一次在内心中.
(7)好好活就是做有意义的事情.
(8)亡羊补牢,为时未晚
(9)科技领域,没有捷径与投机取巧。
(10)有实力,一年365天都是应聘的旺季,没实力,天天都是应聘的淡季。
(11)基础不牢,地动天摇
(12)写博客初心:成长自己,辅助他人。当某一天离开人世,希望博客中的思想还能帮人指引方向.
(13)编写实属不易,若喜欢或者对你有帮助记得点赞+关注或者收藏哦~

JSON解析

1.JSON格式与基本语法

1.1JSON是什么?

1.1.1定义

JSON(Javascript Object Notation) 是一种轻量级的数组交换格式

1.1.2作用

数据标记、存储、传输

1.2JSON解析示意图

在这里插入图片描述

1.3JSON语法格式

1.3.1JSON构建于两种结构

(1)“名称/值”对的集合(A collection of name/value pairs)。
(2)不同的语言中,它被理解为

  • 对象(object)
  • 纪录(record)
  • 结构(struct)
  • 字典(dictionary)
  • 哈希表(hash table)
  • 有键列表(keyed list)
  • 关联数组 (associative array)
  • 值的有序列表(An ordered list of values)
  • 在大部分语言中,它被理解为数组(array)

(3)这些都是常见的数据结构,事实上大部分现代计算机语言都以某种形式支持它们。这使得一种数据格式在同样基于这些结构的编程语言之间交换成为可能。

1.3.2JSON具有以下这些形式
1.3.2.1对象

(1)对象是一个无序的“‘名称/值’对”集合。

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

在这里插入图片描述

1.3.2.2数组

(1)数组是值(value)的有序集合。

(2)一个数组以“[”(左中括号)开始,“]”(右中括号)结束,值之间使用“,”(逗号)分隔。

在这里插入图片描述

"personlist":[
	{
		"name":"张三",
		"age":22
	},
	{
		"name":"李四",
		"age":23
	}
]
1.3.2.3值(Value)

(1)值(value)可以是双引号括起来的字符串(string)、数值(number)、true 、false 、 null 、对象(object)或者数组(array)。

(2)这些结构可以嵌套。

(3)json的Key不能为null

在这里插入图片描述

{
    "url": "https://qqe2.com",    
    "name": "欢迎使用JSON在线解析编辑器",    
    "array": {
        "JSON校验": "http://jsonlint.qqe2.com/",
        "Cron生成": "http://cron.qqe2.com/",
        "JS加密解密": "http://edit.qqe2.com/"
    },    
    "boolean": true,
    "key": null,
    "number": 123,
    "object": {
        "a": "b",
        "c": "d",
        "e": "f"
    }
}
1.3.2.4字符串(string)

(1)字符串(string)是由双引号包围的任意数量Unicode字符的集合,使用反斜线转义。一个字符(character)即一个单独的字符串(character string)。

(2)字符串(String)与C或者Java的字符串非常相似。

在这里插入图片描述

{
	"name":"ZhangSan"
}
1.3.2.5数值(number)

(1)数值(number)也与C或者Java的数值非常相似。
(2)除去未曾使用的八进制与十六进制格式。
(3)除去一些编码细节。

在这里插入图片描述

1.3.2.6格式良好的json

(1)可以被JSON解析库解析,例如gson,fastjson,jackson,这些解析工具都能够解析它。
(2)不是格式良好的JSON

{
"name":33
"age":22
}

1.4gson的基本使用

1.4.1使用gson实现对象的序列化与反序列化

(1)声明Javabean

package com.gdc.jsonlib.entity;

public class GsonBean{

    public int i;

    public String str;

    public GsonBean() {
    }

    public GsonBean(int i, String str) {
        this.i = i;
        this.str = str;
    }

    public int getI() {
        return i;
    }

    public void setI(int i) {
        this.i = i;
    }

    public String getStr() {
        return str;
    }

    public void setStr(String str) {
        this.str = str;
    }
}

(2)将javabean转换为json以及将json重新序列化为javabean

    @Test
    public void testGson(){
        Gson gson = new Gson();
        System.out.println(gson.toJson(1));
        System.out.println(gson.toJson("zero"));

        int[] values = {1,2,3};
        System.out.println(gson.toJson(values));


        int i = gson.fromJson("1",int.class);
        System.out.println("i:"+i);


        //1.将javaBean序列化为json
        GsonBean gsonBean = new GsonBean(1,"str");
        String json = gson.toJson(gsonBean);
        System.out.println("json:"+json);

        //2.将json转换为JavaBean
        GsonBean gsonBean1 = gson.fromJson(json,GsonBean.class);
        System.out.println("gsonBean1:"+gsonBean1);
    }

1.4.2Gson的@SerializedName注解

Gson指定序列化名称及多个名称设置

public class Person {
    /**
     * @SerializedName指定序列化的key
     */
    @SerializedName("name")
    private String name;

    /**
     * @SerializedName:如果指定的序列化名称有多个,默认使用第1个名称
     */
    @SerializedName(value = "age1",alternate = {"age2","age3"})
    private String age;

    public Person() {
    }

    public Person(String name, String age) {
        this.name = name;
        this.age = age;
    }
}

测试

	@Test
    public void testPerson(){
        Person p = new Person("zs","22");
        Gson gson = new Gson();
        String json = gson.toJson(p);
        System.out.println(String.format("json:%s",json));
    }
1.4.3Gson的@Expose注解

Gson设置对象成员变量序列化规则

  • 使用@Expose注解指定序列化规则
  • serialize:变量是否可序列化,默认为true,表示可序列化。
  • deserialize:变量是否可反序列化,默认为true,表示可反序列化。
public class Person1 {

    /**
     * 1.Expose:指定序列化规则
     * 1.1serialize:变量是否可序列化,默认为true,表示可序列化。
     * 1.2deserialize:变量是否可反序列化,默认为true,表示可反序列化。
     */
    @Expose(serialize = true,deserialize = false)
    private String name;

    private String age;

    public Person1() {
    }

    public Person1(String name, String age) {
        this.name = name;
        this.age = age;
    }

}
1.4.4Gson的@Since注解
public class Person2 {


    private String name;

    private String age;

    /**
     * 当前版本>=1.0时才会参与序列化/反序列化,否则忽略
     */
    @Since(1.0)
    private String email;
    /**
     * 当前版本>=1.1时才会参与序列化/反序列化,否则忽略
     */
    @Since(1.1)
    private String password;

    public Person2() {
    }

    public Person2(String name, String age) {
        this.name = name;
        this.age = age;
    }
}

1.4.5Gson的@Until注解
public class Person3 {

    private String name;

    private String age;

    /**
     * 当前版本<=1.1时才会参与序列化/反序列化,否则忽略
     */
    @Until(1.1)
    private String email;
    /**
     * 当前版本<=1.1时才会参与序列化/反序列化,否则忽略
     */
    @Until(1.1)
    private String password;

    public Person3() {
    }

    public Person3(String name, String age) {
        this.name = name;
        this.age = age;
    }
}

1.4.6Gson的@JsonAdapter注解

(1)平时解析json的时候,它最终都是通过反射去解析。
(2)使用反射解析json性能是比较低的,在解析一个Bean类的时候,可以为它定义一个Adapter类,则其解析json的时候,会使用自定义的JsonAdapter类去解析,而不是使用默认的反射去做解析,由此提升解析速度。
(3)JsonWriter:将一个JavaBean写为json String字符串
(4)JsonReader:将json字符串读到JavaBean
(6)TypeAdapter:可用于自定义Json解析器

(5)案例代码:

@JsonAdapter(PersonJsonAdapter.class)
public class Person4 {

    public String name;

    public String age;

    public String email;

    public String password;

    public Person4() {
    }

    public Person4(String name, String age) {
        this.name = name;
        this.age = age;
    }
}
public class PersonJsonAdapter extends TypeAdapter<Person4> {

    @Override
    public void write(JsonWriter out, Person4 person4) throws IOException {
        out.beginObject();
        out.name("name");
        out.value(person4.name);
        out.name("age");
        out.value(person4.age);
        out.endObject();
    }

    @Override
    public Person4 read(JsonReader in) throws IOException {
        in.beginObject();

        in.nextName();
        String name = in.nextString();

        in.nextName();
        String age = in.nextString();

        in.endObject();

        return new Person4(name,age);
    }
}
	@Test
    public void testPerson4(){
        Person4 p = new Person4("张丽华","25");
        Gson gson = new Gson();
        String json = gson.toJson(p);
        System.out.println(String.format("json:%s",json));
    }
1.4.7Gson指定自定义json解析器与版本号
    @Test
    public void testPerson4(){
        Person4 p = new Person4("张丽华","25");
        Gson gson = new GsonBuilder()
        //设置版本号
        .setVersion(1.2)
        //指定自定义解析器
       .registerTypeAdapter(Person4.class,new PersonJsonAdapter()).create();
        String json = gson.toJson(p);
        System.out.println(String.format("json:%s",json));
    }
1.4.8Gson指定输出json格式及日期格式
    @Test
    public void testPerson5(){
        Person4 p = new Person4("张丽华","25");
        Gson gson = new GsonBuilder().setVersion(1.2)//设置版本号
                .setDateFormat("yyyy-MM-dd HH:mm:ss")//设置日期格式
                .setPrettyPrinting()//json自带格式
                .create();
        String json = gson.toJson(p);
        System.out.println(String.format("json:%s",json));
    }
1.4.9JsonWriter与JsonReader进行空处理
public class Foo {

    public String s;
    public int i;

    public Foo() {
        this(null, 5);
    }

    public Foo(String s, int i) {
        this.s = s;
        this.i = i;
    }
}
@Test
    public void testFoo2() {
        Gson gson = new GsonBuilder()
                .setPrettyPrinting()
                .registerTypeAdapter(Foo.class, new TypeAdapter<Foo>() {


                    @Override
                    public void write(JsonWriter out, Foo value) throws IOException {
                        //1.进行非空判断
                        if (null == value) {
                            out.nullValue();
                            return;
                        }
                        //2.把Foo对象制定成你自己定义的格式的字符串进行输出:不一定是json格式了,就看你怎么组织
                        out.beginObject();
                        out.name("s").value(value.s+"张");
                        out.name("i").value(value.i);
                        out.endObject();
                    }

                    @Override
                    public Foo read(JsonReader in) throws IOException {
                        //1.进行非空判断
                        if (in.peek() == JsonToken.NULL) {
                            in.nextNull();
                            return null;
                        }

                        //2.读取json串并封装成Foo对象返回之
                        final Foo foo = new Foo();
                        in.beginObject();
                        while (in.hasNext()) {
                            switch (in.nextName()) {
                            case "s":
                                foo.s = in.nextString();
                                break;
                            case "i":
                                foo.i = in.nextInt();
                                break;
                            }
                        }
                        in.endObject();
                        return foo;
                    }
                })
                .create();

        Foo f = new Foo();
        String json = gson.toJson(f);
        System.out.println(String.format("json:%s",json));
    }
1.4.10使用nullSafe()由系统自动处理value值为null的情况
	@Test
    public void testFoo3() {
        Gson gson = new GsonBuilder()
                .setPrettyPrinting()
                .registerTypeAdapter(Foo.class, new TypeAdapter<Foo>() {

                    @Override
                    public void write(JsonWriter out, Foo value) throws IOException {
                        out.beginObject();
                        out.name("s").value(value.s);
                        out.name("i").value(value.i);
                        out.endObject();
                    }

                    @Override
                    public Foo read(JsonReader in) throws IOException {
                        //读取json串并封装成Foo对象返回之
                        final Foo foo = new Foo();
                        in.beginObject();
                        while (in.hasNext()) {
                            switch (in.nextName()) {
                            case "s":
                                foo.s = in.nextString();
                                break;
                            case "i":
                                foo.i = in.nextInt();
                                break;
                            }
                        }
                        in.endObject();
                        return foo;
                    }
                }.nullSafe()).create();

        Foo foo = new Foo();
        String json = gson.toJson(foo);
        System.out.println(String.format("json:%s",json));
    }

(2)nullSafe源码com.google.gson.TypeAdapter#nullSafe

  public final TypeAdapter<T> nullSafe() {
    return new TypeAdapter<T>() {
      @Override public void write(JsonWriter out, T value) throws IOException {
        if (value == null) {
          out.nullValue();
        } else {
          TypeAdapter.this.write(out, value);
        }
      }
      @Override public T read(JsonReader reader) throws IOException {
        if (reader.peek() == JsonToken.NULL) {
          reader.nextNull();
          return null;
        }
        return TypeAdapter.this.read(reader);
      }
    };
  }
1.4.11JSON格式错误兼容处理

(1)错误描述

  • 遇到com.google.gson.JsonSyntaxException: java.lang.IllegalStateException错误,经常客户端开发与服务端开发相互推责。

  • 开发环境与测试环境数据自己造的,没有一点点问题,但是上了生产环境之后,结果后台没处理好,返回一个null,程序就崩溃了,即错误会表现在客户端,领导追自己的责任。

  • 为了程序的移定性,客户端也一定要去解决兼容性与稳定性问题。

(2)异常

com.google.gson.JsonSyntaxException: 
java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at line 3 column 17 path
    @Test
    public void test2() {
        String json = "{\n" +
                "    \"name\": \"java\",\n" +
                "    \"authors\": \"\"\n" +
                "}";
        Gson gson = new Gson();
        GsonError1 gsonError1 = gson.fromJson(json, GsonError1.class);

        System.out.println(gsonError1);
    }
1.4.12JSON格式错误兼容处理方案

(1)自定义TypeAdapter去处理
(2)自定义JsonDeserializer去处理

  • 即从JsonElement中解析
public class GsonError1Deserializer implements JsonDeserializer<GsonError1> {

    @Override
    public GsonError1 deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        final JsonObject jsonObject = json.getAsJsonObject();
        final JsonElement jsonTitle = jsonObject.get("name");
        final String name = jsonTitle.getAsString();

        JsonElement jsonAuthors = jsonObject.get("authors");
        GsonError1 gsonError1 = new GsonError1();

        if(jsonAuthors.isJsonArray()){
            //1.如果数组类型,此种情况是我们需要的
            AuthorsBean[] authors = context.deserialize(jsonAuthors,
                    AuthorsBean.class);
            gsonError1.setAuthors(Arrays.asList(authors));
        }else{
            //2.此种情况为无效情况
            gsonError1.setAuthors(null);
        }
        gsonError1.setName(name);
        return gsonError1;
    }
}
public class AuthorDeserializer implements JsonDeserializer<AuthorsBean> {

    @Override
    public AuthorsBean deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        JsonObject jsonObject = json.getAsJsonObject();

        AuthorsBean author = new AuthorsBean();
        author.setId(jsonObject.get("id").getAsString());
        author.setName(jsonObject.get("name").getAsString());

        return author;
    }
}
    @Test
    public void test3() {
        String json = "{\n" +
                "    \"name\": \"java\",\n" +
                "    \"authors\": \"\"\n" +
                "}";

        GsonBuilder gsonBuilder = new GsonBuilder();

        //注册TypeAdapter
        gsonBuilder.registerTypeAdapter(GsonError1.class,new GsonError1Deserializer());
        gsonBuilder.registerTypeAdapter(AuthorsBean.class, new AuthorDeserializer());

        Gson gson = gsonBuilder.create();
        GsonError1 gsonError1 = gson.fromJson(json, GsonError1.class);


        System.out.println(gsonError1);
    }
       return author;
    }
}

2.打赏鼓励

感谢您的细心阅读,您的鼓励是我写作的不竭动力!!!

2.1微信打赏

在这里插入图片描述

2.2支付宝打赏

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值