JSON的学习与使用

Posted 小李不秃

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JSON的学习与使用相关的知识,希望对你有一定的参考价值。

公众号:小李不秃,Java 原创博主
阅读本文大概需要 7.8 分钟

前言什么是 JSON为什么有 JSON如何使用 JSONJSON 的数据结构Json 在 javaScript 中的使用操作 Json 对象操作 JSON 数组JSON.parse()JSON.stringify()evalJson 在 Java 中的使用Json-libGsonJacksonfastJson总结参考推荐阅读

前言

我们在进行软件开发的过程中,服务与服务之间会进行相互的调用。在数据进行传输前,我们通常会将数据转化成 JSON 的格式进行传输,比如 ajax 调用请求,接收传过来的 JSON 数据,javascript 就可以对传过来的数据进行直接的调用。

本篇文章会讲解以下的内容:

  • 什么是 JSON---what
  • 为什么有 JSON---why
  • 如何使用 JSON---How
    • JSON 的数据结构
    • Json 在 javascript 中的使用
    • Json 在 Java 中的使用

什么是 JSON

JSON 全拼 Java Script Object Notation,JavaScript 对象表示法。是一种由道格拉斯·克罗克福特构想和设计、轻量级的数据交换语言,该语言以易于让人阅读的文字为基础,用来传输由属性值或者序列性的值组成的数据对象。尽管 JSON 是 JavaScript 的子集,但是 JSON 是独立于语言的文本格式。

JSON 数据格式与语言无关。即便它源自 JavaScript,但很多编程语言都支持 JSON 格式数据的生成和解析,例如在 Java 中就有 fastjson、gson 等工具类对 JSON 进行操作。

小结

  • JSON 是数据交换语言。
  • JSON 是独立于任何程序语言的文本格式。

为什么有 JSON

提到这里,就不得不和 XML 进行比较了。XML 也是可以作为跨平台的数据交换格式。但是为什么我们大多用 JSON,而不用 XML 呢?有下面几点原因:

  • javaScript 原生支持 JSON,解析速度更快。而 XML 解析成 DOM 对象的时候,浏览器会有差异。

  • 对于 AJAX 应用程序来说,JSON 比 XML 更快更易使用。

  • 使用 XML :读取 XML 文档,使用 XML DOM 循环遍历文档,将读取值存入变量。

  • 使用 JSON:读取 JSON 字符串,JSON.parse 解析 JSON 字符串。

综上,我们更倾向于选择 JSON 来进行数据交换。

如何使用 JSON

JSON 的数据结构

  • 对象

JSON 对象使用在 大括号“{}”中书写,对象可以有多个键值对(key/value)。

key 必须是字符串,value 可以是合法的 JSON 数据类型(字符串、数字、对象、数组、布尔值或null)

key 和 value 中使用冒号“:”分割,键值对之间用逗号“,”分割。

{"name":"关注公众号:小李不秃","age":18,"money":null}

 

  • 数组

JSON 数组在中括号“[]”中书写。JSON 中数组值必须是合法的 JSON 数据类型。

[    
    {"name":"张三"},
    {"name":"李四"),
    {"name":"王五"}
]

Json 在 javaScript 中的使用

操作 Json 对象

  • 访问对象值

可以使用点号“.”来访问对象的值,也可以使用中括号“[]”来访问对象的值。

var data, x;
data = {"name":"xiaoli""area":"china""money":null};
x = data.name; #或者myObj["name"]

运行结果:xiaoli

 

  • 循环对象

使用 for-in 来循环对象的属性

var data, x;
data = {"name":"xiaoli""area":"china""money":null};
for(x in data){
    console.log(x + ":" + data[x]);
}

运行结果:
name:xiaoli
area:china 
money:null

 

  • 修改值

可以使用点号“.”来修改 JSON 对象的值,也可以使用中括号“[]”修改 JSON 对象的值。

data.money = 100;
data["money"] = 100;

 

  • 删除值

通过 delete 关键字来删除 JSON 对象的属性。

delete data.money;
delete data["money"]

操作 JSON 数组

  • 访问 JSON 数组值

通过索引值来访问数组。

var myObj, x;
myObj = {
    "name":"网站",
    "num":3,
    "sites":[ "Google""Runoob""Taobao" ]
}
x = myObj.sites[0];

运行结果:Google

 

  • 循环数组

通过 for-in 来访问数组。

var myObj, i, x = "";
myObj = {
    "name":"网站",
    "num":3,
    "sites":[ "Google""Runoob""Taobao" ]
};

for (i in myObj.sites) {
    x += myObj.sites[i] + "<br>";
}

运行结果:

Google
Runoob
Taobao

也可以通过 for 来循环访问数组。

var myObj, i, x = "";
myObj = {
    "name":"网站",
    "num":3,
    "sites":[ "Google""Runoob""Taobao" ]
};

for (i = 0; i < myObj.sites.length; i++) {
    x += myObj.sites[i] + "<br>";
}

javaScript 中的 for-in 类似于 Java 中的 foreach 。

  • 修改数组元素

可以通过索引值来修改数组元素。

myObj.sites[1] = "Github";

 

  • 删除数组元素

使用 delete 来删除数组元素

delete myObj.sites[1];

这里需要注意 delete 并没有彻底删除元素,而是删除它的值,仍然会保留空间。运算符 delete 只是将该值设置为 undefined,而不会影响数组的长度。如果想要实现彻底删除,需要使用 splice() 方法。

var myObj, i, x = "";
myObj = {
    "name":"网站",
    "num":3,
    "sites":[ "Google""Runoob""Taobao" ]
};
delete myObj.sites[1];

x = "sites.length = " + myObj.sites.length + "<br><br>";

for (i=0;i<myObj.sites.length;i++) {
    console.log(i + ":" + myObj.sites[i]);
    x += i + " " + myObj.sites[i] + "<br>";
}

document.getElementById("demo").innerhtml = x;

运行结果:
0:Google
1:undefined
2:Taobao
myObj.sites.splice(1,1);

运行结果:
0:Google
1:Taobao

JSON.parse()

JSON 通常与服务端交换数据,接收服务器传输的数据时一般是字符串,我们可以通过 JSON.parse() 方法将数据转换为 JavaScipt 对象。

具体使用

var obj = JSON.parse(\'{"name":"关注公众号:小李不秃","age":18,"money":null}\');
console.log(obj.name + ":" + obj.age + ":" + obj.money)

运行结果:关注公众号:小李不秃:18null

JSON 存 Date 对象,需要将其转换为字符串,之后再将字符串转换为 Date 对象。

var text = \'{ "name":"小李不秃", "initDate":"2020-1-17"}\';
var obj = JSON.parse(text, function (key, value{
    if (key == "initDate") {
        return new Date(value);
    } else {
        return value;
}});

console.log(obj.name + ":" + obj.initDate);

运行结果:小李不秃:Fri Jan 17 2020 00:00:00 GMT+0800 (中国标准时间)

JSON.stringify()

JSON 在向服务端传输的数据一般是字符串,所以我们可以使用 JSON.stringify() 方法将 JavaScript 对象转换为字符串。

具体使用

var obj = {"name":"xiaoli""area":"china""money":null};
console.log(obj);
var myJSON = JSON.stringify(obj);
console.log(myJSON);

运行结果

eval

对于服务器返回的 JSON 字符串,如果 jQuery 异步请求没做类型说明,或者以字符串方式接收,那么需要做一次对象化处理,方式不是太麻烦,就是将该字符串放于 eval() 中执行一次。这种方式也适合以普通 javascipt 方式获取 json 对象,以下举例说明:

var u = eval(\'(\'+user+\')\');

为什么要 eval 这里要添加 (\'(\'+user+\')\') 呢?

原因在于:eval 本身的问题。 由于 json 是以 {} 的方式来开始以及结束的,在 js 中,它会被当成一个语句块来处理,所以必须强制性的将它转换成一种表达式。

加上圆括号的目的是迫使 eval 函数在处理 JavaScript 代码的时候强制将括号内的表达式(expression)转化为对象,而不是作为语句(statement)来执行。举一个例子,例如对象字面量 {},如若不加外层的括号,那么 eval 会将大括号识别为 javascript 代码块的开始和结束标记,那么{}将会被认为是执行了一句空语句。所以下面两个执行结果是不同的:

alert(eval("{}"); // return undefined
alert(eval("({})");// return object[Object]

测试用例

var user = \'{"name":"关注公众号:小李不秃","age":18,"money":null,\'+  
    \'showInfo:function(){\'+  
    \'document.write("姓名:"+this.name+"<br/>");\'+  
    \'document.write("年龄:"+this.age+"<br/>");\'+  
    \'document.write("金钱:"+this.money+"<br/>");}}\'
var u = eval(\'(\'+user+\')\');  
u.showInfo();

运行结果:

姓名:关注公众号:小李不秃
年龄:18
金钱:null

Json 在 Java 中的使用

在 Java 中,解析 JSON 的第三方工具类有很多,常用的有几种:

  • Json-lib
  • Gson
  • Jackson
  • fastjson

统一用下面的 Person 类作为示例

@Data
public class Person {

    private String name;
    private Integer age;

    public Person() {
    }

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

那我们对这几个工具类进行一一介绍:

Json-lib

Json-lib 是一个 Java 类库,提供将 Java 对象(包括:beans,maps,collections,java arrays 和 XML等)和 JSON 互相转换的功能。

引入相关 jar 包

  • commons-io-2.0.1.jar
  • commons-lang-2.5.jar
  • commons-collections-3.1.jar
  • commons-beanutils-1.7.0.jar
  • ezmorph-1.0.3.jar
  • json-lib-2.1-jdk15.jar

Json-lib 工具类

封装一个 Json-lib 工具类,方便测试用。

// Json-lib 工具类
public class JsonLibUtils {
    /**
     * bean 转换为 Json 字符串
     */

    public static String bean2json(Object o){
        JSONObject jsonObject = JSONObject.fromObject(o);
        return jsonObject.toString();
    }
    /**
     * json 转换为 bean
     */

    public static Object json2bean(String s,Class c){
        JSONObject jsonObject = JSONObject.fromObject(s);
        return JSONObject.toBean(jsonObject,c);
    }
    /**
     * list 转换为 Json 字符串
     */

    public static String list2json(List list){
        JSONArray jsonArray = JSONArray.fromObject(list);
        return jsonArray.toString();
    }
    /**
     * json 转换为 list
     */

    public static List json2List(String s){
        return JSONArray.fromObject(s);
    }
    /**
     * set 转换为 Json 字符串
     */

    public static String set2json(Set set){
        JSONArray jsonArray = JSONArray.fromObject(set);
        return jsonArray.toString();
    }

    /**
     * json 转换为 set
     */

    public static Set json2Set(String json) {
        Set<Person> set = new HashSet<>(json2List(json));
        return set;
    }
    /**
     * map 转换为 Json 字符串
     */

    public static String map2json(Map map){
        JSONObject jsonObject = JSONObject.fromObject(map);
        return jsonObject.toString();
    }
    /**
     * json 转换为 map
     */

    public static Map<Object, Object> json2Map(String json) {
        JSONObject jsonObject = JSONObject.fromObject(json);
        Map<Object, Object> map = (Map)jsonObject;
        return map;
    }
}

示例代码:

public class JsonlibTest {

    public static void main(String[] args) {
        //1. bean 和 json 互转
        Person person = new Person("xiaoli",18);
        String json = JsonLibUtils.bean2json(person);
        // {"age":18,"name":"xiaoli"}
        Person person2 = (Person)JsonLibUtils.json2bean(json, Person.class);

        //2. list 和 json 互转
        List<Person> list = new ArrayList<Person>();
        list.add(new Person("李四",10));
        list.add(new Person("王五",20));
        String listJson = JsonLibUtils.list2json(list);
        // [{"age":10,"name":"李四"},{"age":20,"name":"王五"}]
        List json2List = JsonLibUtils.json2List(listJson);

        //3. map 转 json
        Map<String,Person> map = new HashMap<String,Person>();
        map.put("map1",new Person("李四",10));
        map.put("map2",new Person("王五",20));
        String mapJson = JsonLibUtils.map2json(map);
        // {"map2":{"age":20,"name":"王五"},"map1":{"age":10,"name":"李四"}}
        Map<Object, Object> map2 = JsonLibUtils.json2Map(mapJson);

        //4. set 与 json 互转
        Set<Person> set = new LinkedHashSet<Person>();
        set.add(new Person("李四",10));
        set.add(new Person("王五",20));
        String setJson = JsonLibUtils.set2json(set);
        // [{"age":10,"name":"李四"},{"age":20,"name":"王五"}]
        JsonLibUtils.json2Set(setJson);
    }
}

缺点

  • 依赖的包过多。
  • 复杂类型的转换有缺陷,比如一个类里面会出现另一个类的list或者map集合,json-lib从json到bean的转换就会出现问题。
  • 不推荐使用 Json-lib 的 n 个理由

小结

json-lib 提供两个对象,分别是 JSONObjectJSONArray,分别对应着 JSON 的两个数据结构。根据需要选取转换的对象。但是由于 json-lib 已经 n 多年没有维护,缺陷较多,在功能和性能方面已经无法满足我们的需求,所以尽量还是不用为好。

Gson

Gson 是 Google 公

以上是关于JSON的学习与使用的主要内容,如果未能解决你的问题,请参考以下文章

错误代码:错误域 = NSCocoaErrorDomain 代码 = 3840“JSON 文本没有以数组或对象和允许未设置片段的选项开头。”

从片段中的json获取值

json 个人的vscode的代码片段

使用 json rereiver php mysql 在片段中填充列表视图

Xitrum学习笔记08 - JavaScript and JSON

实用代码片段将json数据绑定到html元素 (转)