Json的官方解析

JSON介绍

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。 易于人阅读和编写。同时也易于机器解析和生成。 它基于JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。 这些特性使JSON成为理想的数据交换语言。

JSON的两种格式

  • ​ “名称/值”对的集合(A collection of name/value pairs)。
  • 值的有序列表(An ordered list of values)。在大部分语言中,它被理解为数组(array)。

JSON的具体格式

  • 对象是一个无序的“‘名称/值’对”集合。一个对象以“{”(左括号)开始,“}”(右括号)结束。每个“名称”后跟一个“:”(冒号);“‘名称/值’ 对”之间使用“,”(逗号)分隔。
  • 值的有序列表(An ordered list of values)。在大部分语言中,它被实现为数组(array),矢量(vector),列表(list),序列(sequence)。

JSON的例子

对象的格式:
{
  "name":"xxxx",
  "age":18,
  "address":"yyyyy"
}
列表的格式:
[
  {
  "name":"xxxx",
  "age":18,
  "address":"yyyyy"
  },
  {
  "name":"xxxx",
  "age":18,
  "address":"yyyyy"
  }
]

ps:

JSONObject是无序的
JSONArray是有序的

标准的json格式:key都是字符串且使用双引号包裹,value可以是任意的数据类型,例如:整形,字符串,对象,数组等。

JSON中国


JSON官方的解析

jsonObject的例子

在resource下的user.json文件

{
  "name": "gakkij",
  "age": 18,
  "address": "东京"
}

博主创建的maven项目,可以自行选择IDE。

pom:

<dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.json/json -->
        <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
            <version>20160810</version>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.1</version>
        </dependency>

        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>1.8.3</version>
        </dependency>

        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.1.1</version>
        </dependency>

        <dependency>
            <groupId>commons-collections</groupId>
            <artifactId>commons-collections</artifactId>
            <version>3.2.1</version>
        </dependency>

        <dependency>
            <groupId>net.sf.ezmorph</groupId>
            <artifactId>ezmorph</artifactId>
            <version>1.0.6</version>
        </dependency>

</dependencies>

程序
        File jsonFile = ResourceUtils.getFile("classpath:user.json");
        String json = FileUtils.readFileToString(jsonFile);

        JSONObject jsonObject = new JSONObject(json);
        String name = jsonObject.getString("name");
        int age = jsonObject.getInt("age");
        String address = jsonObject.getString("address");
        User user = new User(name, age, address);
        System.out.println(user);
public class User {

    private String name;
    private int age;
    private String address;

    省略: set,get 方法
}

说明:首先判断你的json文件的根是对象,还是列表,是对象就使用:JSONObject,是列表就使用:JSONArray。

jsonObject对象,可以通过各种:getXXX方法来获取 key 对应的 value 值,int类型就是:getInt;String类型就是:getString,如果value是 {}对象,就是:getJSONObject;如果是[] 列表类型,就是:getJSONArray。


jsonArray的例子

在resource目录下:

section.json

[
    {
        "id": 1580615,
        "name": "皮的嘛",
        "packageName": "com.renren.mobile.android",
        "iconUrl": "app/com.renren.mobile.android/icon.jpg",
        "stars": 2,
        "size": 21803987,
        "downloadUrl": "app/com.renren.mobile.android/com.renren.mobile.android.apk",
        "des": "2011-2017 你的铁头娃一直在这儿。中国最大的实名制SNS网络平台,嫩头青"
    },
    {
        "id": 1540629,
        "name": "不存在的",
        "packageName": "com.ct.client",
        "iconUrl": "app/com.ct.client/icon.jpg",
        "stars": 2,
        "size": 4794202,
        "downloadUrl": "app/com.ct.client/com.ct.client.apk",
        "des": "斗鱼271934走过路过不要错过,这里有最好的鸡儿"
    }
]
程序
File jsonFile = ResourceUtils.getFile(s);
        String json = FileUtils.readFileToString("classpath:section.json");
        System.out.println(json);
        System.out.println("===========");
        JSONArray jsonArray = new JSONArray(json);
        List<Section> sectionList = new ArrayList<>();
        for (int i = 0; i < jsonArray.length(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            String des = jsonObject.getString("des");
            int size = jsonObject.getInt("size");
            String name = jsonObject.getString("name");
            String downloadUrl = jsonObject.getString("downloadUrl");
            int id = jsonObject.getInt("id");
            String packageName = jsonObject.getString("packageName");
            String iconUrl = jsonObject.getString("iconUrl");
            int stars = jsonObject.getInt("stars");
            Section section = new Section(id, name, packageName, iconUrl, stars, size, downloadUrl, des);
            sectionList.add(section);
        }
        sectionList.forEach(section -> {
            System.out.println(section);
        });

说明:

json文件的根是:[] 开头的话,就使用 :JSONArray 来解析。

通过遍历 JSONArray 对象来 获取其中的值,注意:JSONArray是有序的。

jsonArray的各种 get 方法,是需要判断 json文件中[]列表的value具体的类型,这里因为都是{}对象,因此,我统一都是使用:jsonArray.getJSONObject(i) 来解析的,如果[]中的类型不一致,那就需要分开处理了。


[
  12,
  "gakkj",
  {
    "name": "jacklove",
    "age": 18,
    "address": "北京"
  }
]
        File jsonFile = ResourceUtils.getFile(s);
        String json = FileUtils.readFileToString(jsonFile);

        JSONArray jsonArray = new JSONArray(json);

        int id = jsonArray.getInt(0);
        String love = jsonArray.getString(1);
        JSONObject jsonObject = jsonArray.getJSONObject(2);
        String name = jsonObject.getString("name");
        int age = jsonObject.getInt("age");
        String address = jsonObject.getString("address");

        System.out.println("id:"+id+",love:"+love+",  
                           ["+"name:"+name+",age:"+age+",address:"+address+"]");

案例

当json文件中,没有出现该key时,解析会出现什么呢?

{
  "name": "gakki",
  "age": 18,
  "address": "东京"
}
File jsonFile = ResourceUtils.getFile(s);
String json = FileUtils.readFileToString(jsonFile);

JSONObject jsonObject = new JSONObject(json);

String name = jsonObject.getString("name");
System.out.println(name);
String nokown = jsonObject.getString("unkown");
System.out.println(nokown);

能看到:gakki解析出来了,但是不存在:unknow,就会直接抛出异常了。


因此,为了提供程序的鲁棒性,解析之前请先判断是否存在:

        File jsonFile = ResourceUtils.getFile(s);
        String json = FileUtils.readFileToString(jsonFile);

        JSONObject jsonObject = new JSONObject(json);

        if(jsonObject.has("name")){
            String name = jsonObject.getString("name");
            System.out.println(name);
        }
        boolean unknow1 = jsonObject.has("unknow");
        System.out.println(unknow1);

可以看到,我们可以使用:has(“xxx”) 来判断是否存在该key。


{
  "name": "gakki",
  "age": 18,
  "address": "东京",
  "host": null
}

当前:host是null。

        File jsonFile = ResourceUtils.getFile(s);
        String json = FileUtils.readFileToString(jsonFile);

        JSONObject jsonObject = new JSONObject(json);

        boolean host = jsonObject.has("host");
        System.out.println(host);
        boolean aNull = jsonObject.isNull("host");
        System.out.println(aNull);

执行:

true
true

说明:只有key存在,has函数就返回true,不管value是不是null,isNull函数来判断value是不是null。


有没有更好的方法,不需要判断key是否存在,如果key存在就返回value,不存在就返回Null,不抛出异常呢?

        JSONObject jsonObject = new JSONObject(json);

        String unknow = jsonObject.optString("unknow");
        System.out.println(unknow == null);
        System.out.println(unknow);
        String host = jsonObject.optString("host");
        System.out.println(host == null);
        System.out.println(host);
        int size = jsonObject.optInt("size");
        System.out.println(size);

说明:使用optXXX() 方法,当key不存在,返回默认值,例如:optString()就是返回:””, 注意不是null。optInt():返回0;optBoolean:返回:false。

ps:optXXX() 方法还有一个重载的方法,optSting(“xxx”,”default”) ,第二个参数就是当xxx不存在时,返回的值,不再是默认的空字符串!!!

        JSONObject jsonObject = new JSONObject(json);

        String unknow = jsonObject.optString("unknow","you know");
        System.out.println(unknow);
        String host = jsonObject.optString("host","皇家");
        System.out.println(host);
        int size = jsonObject.optInt("size",17);
        System.out.println(size);
        System.out.println(jsonObject.optBoolean("sss",true));
you know
皇家
17
true

枚举类型的解析:

{
  "color": "RED"
}
package com.liuzhuo.json.domain;

/**
 * @Author liuzhuo
 * @Date 2019/12/14 11:20 上午
 * @Version 1.0
 */
public enum Color {
    RED,
    BULE,
    YELLOW
}

JSONObject jsonObject = new JSONObject(json);

Color color = jsonObject.getEnum(Color.class, "color");
System.out.println(color);
RED

Process finished with exit code 0

枚举定义自己的字段时:

package com.liuzhuo.json.domain;

/**
 * @Author liuzhuo
 * @Date 2019/12/14 11:20 上午
 * @Version 1.0
 */
public enum Color {

    RED("red"),
    BULE("bule"),
    YELLOW("yyyy");

    private String fieldName;

    Color(String fieldName) {
        this.fieldName = fieldName;
    }

    public static Color getColorByFieldName(String fieldName) {
        for (Color value : Color.values()) {
            if (value.fieldName.equals(fieldName)) {
                return value;
            }
        }
        return null;
    }

    public String getFieldName() {
        return fieldName;
    }
}

{
  "color": "red"  // 这里是我自己定义的field字段的值
}
Exception in thread "main" org.json.JSONException: JSONObject["color"] is not an enum of type "Color".
    at org.json.JSONObject.getEnum(JSONObject.java:495)
    at com.liuzhuo.json.JsonParse.parseJson3(JsonParse.java:46)
    at com.liuzhuo.json.JsonParse.main(JsonParse.java:36)

Process finished with exit code 1

运行抛出异常,说明不能使用自己定义 的字段 来获取,枚举类型。

总结

  • 解析之前,请观看根是对象还是列表(数组),对象使用:JSONObject,数组使用:JSONArray。

  • 对象解析时,根据value的类型,调用相应的 getXXX() 方法来获取value值。

  • 数组解析时,因为数组是有序的,因此请注意,每个数组中元素类型是否是一致的,如果是就使用for循环遍历来解析,否则就必须根据数组中,不同的坐标下的元素来分开解析。

  • 当key不存在时,使用:getXXX() 方法会抛出异常,可以使用:has() 方法提前判断是否存在,isNull()方法来判断值是不是null。

  • 当key不存在时,不想抛出异常,请使用 optXXX() 方法,不存在会返回相应类型的默认值,String:空字符串,int:0,boolean:false。也可以使用 带有两个参数的optXXX(,) 方法,指定需要返回的值。

  • 缺点:没有直接将json字符串解析出javaBean对象,这个 不太方便,每个javaBean的属性需要我们自己解析出来后,手动拼接。

后续,我会陆续介绍:GSON、fastJSON,jackSon, 并且分析这些json解析的优缺点。


  转载请注明: 解忧杂货店 Json的官方解析

  目录