JSON 全知全解:深入探索 JSON 的奥秘


一、JSON 基础认知

(一)JSON 的定义与历史

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,由 Douglas Crockford 在 2001 年开始推广使用。在 2005 - 2006 年,JSON 正式成为主流的数据格式,雅虎和谷歌等企业开始广泛地使用。JSON 基于 ECMAScript(欧洲计算机协会制定的 js 规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据,易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。

(二)JSON 的语法规则

JSON 的语法规则十分简单,包含六个构造字符:begin-array(“[”)、begin-object(“{”)、end-array(“]”)、end-object(“}”)、name-separator(“:”)、value-separator(“,”)。值的类型有七种:字符串、数值、对象、数组、true、false、null。对象用花括号{}表示,是键值对的集合,键值对之间用逗号隔开;数组用方括号[]表示,是值的有序列表,值之间用逗号分隔。字符串与 C 或者 Java 的字符串非常相似,是由双引号包围的任意数量 Unicode 字符的集合,使用反斜线转义。数字也与 C 或者 Java 的数值非常相似,除去未曾使用的八进制与十六进制格式。

(三)JSON 与 JS 对象的关系

JSON 是 JS 对象的字符串表示法,本质是一个字符串。如 var obj = {a: ‘Hello’, b: ‘World’}; 这是一个对象,var json = ‘{“a”: “Hello”, “b”: “World”}’; 这是一个 JSON 字符串。要实现从 JSON 字符串转换为 JS 对象,使用 JSON.parse()方法;要实现从 JS 对象转换为 JSON 字符串,使用 JSON.stringify()方法。例如,var obj = JSON.parse(‘{“a”: “Hello”, “b”: “World”}’); 结果是 {a: ‘Hello’, b: ‘World’};var json = JSON.stringify({a: ‘Hello’, b: ‘World’}); 结果是 ‘{“a”: “Hello”, “b”: “World”}’。两者在含义、传输和表现上存在不同点:JSON 是一种数据格式,JS 对象是类的实例;JSON 可以跨平台传输,速度快,JS 对象不能传输;JSON 的键必须加双引号,值不能是函数、undefined、NaN,而 JS 对象的键可以不加引号,值可以是函数、对象等数据。

二、JSON 在不同语言中的用法

(一)JavaScript 中的 JSON 操作

在 JavaScript 中,操作 JSON 对象和字符串有多种方法。例如,可以使用 eval()、JSON.parse()、JSON.stringify()等。JSON 字符串: var str1 = ‘{ “name”: “haorooms”, “sex”: “man” }’;,要将其转换为 JSON 对象,可以使用以下方法:

  1. var obj = eval(‘(’ + str1 + ‘)’);,这是一种将 JSON 字符串转换为 JSON 对象的方法,但要注意安全风险,因为 eval() 可能执行恶意代码。
  2. var obj = str1.parseJSON();,不过如果 obj 本来就是一个 JSON 对象,使用此方法处理后可能会抛出语法异常。
  3. var obj = JSON.parse(str1);,这是一种安全可靠的将 JSON 字符串转换为 JSON 对象的方法。
    反过来,要将 JSON 对象转化为 JSON 字符串,可以使用 toJSONString()或者全局方法 JSON.stringify()。例如:var last=obj.toJSONString(); 或者 var last=JSON.stringify(obj);。

(二)Java 中的 JSON 操作

在 Java 中,可以通过 json-lib.jar 包及相关类操作 JSON。JSONObject 和 JSONArray 是常用的类。例如,要将对象转换为 JSONObject 对象,可以使用 JSONObject.fromObject(object)方法,然后使用 toString方法就可以获取 json 字符串。这个方法既可以传入对象,也可以传入 json 字符串。要把 json 字符串转为对象,可以使用 JSONObject.toBean(JSONObject, class)方法。
此外,Java 中还可以进行各种集合类型与 JSONArray 的转换以及对象类型与 JSONObject 的转换。例如:

  1. 布尔数组转换为 JSONArray:boolean[] boolArray = new boolean[] { true, false, true };JSONArray jsonArray = JSONArray.fromObject(boolArray);,输出:[true,false,true]。
  2. List 转换为 JSONArray:List list = new ArrayList();list.add( “first” );list.add( “second” );JSONArray jsonArray = JSONArray.fromObject( list );,输出:[“first”,“second”]。

(三)PHP 中的 JSON 操作

在 PHP 中,使用 json_encode()和 json_decode()函数将数组和对象转换为 JSON 格式及反之。

  1. json_encode():对变量进行 JSON 编码。语法为 json_encode ( $value [, o p t i o n s = 0 ] ) 。注意该函数只对 U T F 8 编码的数据有效,执行成功返回 J S O N 数据,否则返回 F A L S E 。例如: options = 0 ] )。注意该函数只对 UTF8 编码的数据有效,执行成功返回 JSON 数据,否则返回 FALSE。例如: options=0])。注意该函数只对UTF8编码的数据有效,执行成功返回JSON数据,否则返回FALSE。例如:book = array(‘a’=>‘xiyouji’,‘b’=>‘sanguo’,‘c’=>‘shuihu’,‘d’=>‘hongloumeng’); j s o n = j s o n e n c o d e ( json = json_encode( json=jsonencode(book);,浏览器打印出的结果如下:{“a”:“xiyouji”,“b”:“sanguo”,“c”:“shuihu”,“d”:“hongloumeng”}。
  2. json_decode():对 JSON 数据进行解码,转换为 PHP 变量。语法为 json_decode ( j s o n [ , json [, json[,assoc = false [, $depth = 512 [, $options = 0 ]]])。当 a s s o c 值为 T R U E 时返回数组, F A L S E 时返回对象。例如: assoc 值为 TRUE 时返回数组,FALSE 时返回对象。例如: assoc值为TRUE时返回数组,FALSE时返回对象。例如:book = array(‘a’=>‘xiyouji’,‘b’=>‘sanguo’,‘c’=>‘shuihu’,‘d’=>‘hongloumeng’); j s o n = j s o n e n c o d e ( json = json_encode( json=jsonencode(book); a r r a y = j s o n d e c o d e ( array = json_decode( array=jsondecode(json,TRUE); o b j = j s o n d e c o d e ( obj = json_decode( obj=jsondecode(json);var_dump( a r r a y ) ; v a r d u m p ( array);var_dump( array);vardump(obj);,浏览器打印出的结果如下:array(4) { [“a”]=> string(7) “xiyouji” [“b”]=> string(6) “sanguo” [“c”]=> string(6) “shuihu” [“d”]=> string(11) “hongloumeng” }object(stdClass)#2 (4) { [“a”]=> string(7) “xiyouji” [“b”]=> string(6) “sanguo” [“c”]=> string(6) “shuihu” [“d”]=> string(11) “hongloumeng” }。

(四)jQuery 获取 JSON 方法

在 jQuery 中,通过 getJSON()函数获取 JSON 数据。语法为 jQuery.getJSON( url [, data ][, success ])。参数 success指定的回调函数只有在请求成功时才会执行,如果请求失败则不作任何处理。返回值为 jqXHR类型,返回发送该请求的 jqXHR对象。
例如:

  1. $.getJSON(“index.php?type=json”);,获取 index.php?type=json的 JSON 数据,但不作任何处理。
  2. $.getJSON(“index.php?type=json”,function(data, textStatus, jqXHR){ alert( data.id );alert( data.name );});,获取 index.php?type=json的 JSON 数据,获取成功时弹出对话框,显示数据中的 id 和 name。

三、JSON 的应用场景

(一)网络数据交换

  1. Web 应用:在前后端分离架构中,服务器端通过 HTTP 响应将数据以 JSON 格式发送给客户端(如浏览器)。例如,一个电商网站,服务器可以将商品列表、用户信息等数据以 JSON 格式传递给客户端,客户端的 JavaScript 代码解析 JSON 后动态更新网页内容。据统计,超过 70%的现代 Web 应用采用这种方式进行数据交互。
  2. AJAX 异步请求:浏览器使用 AJAX 技术发起异步请求,服务器返回 JSON 数据,实现局部内容的动态加载和更新,无需刷新整个页面。比如在社交平台上,当用户下拉页面时,通过 AJAX 异步请求获取新的动态内容,以 JSON 格式返回并展示给用户,极大地提升了用户体验。
  3. RESTful API:JSON 是现代 API 设计的标准数据格式之一,用于规定请求参数和响应数据结构。API 使用者通过发送 JSON 请求到服务器,并接收 JSON 格式的响应结果。例如,许多第三方天气 API 采用 RESTful 架构,以 JSON 格式返回天气数据,方便开发者在不同的应用中集成天气信息。

(二)数据存储

  1. 数据库存储:
    1.1. NoSQL 数据库:某些 NoSQL 数据库(如 MongoDB)直接支持 JSON 作为存储格式。MongoDB 以其灵活的数据模型和高效的存储方式,在处理大量半结构化数据时表现出色。据行业数据显示,在大数据和实时数据分析领域,MongoDB 的市场占有率不断提升,其中 JSON 格式的数据存储功不可没。
    1.2. 关系型数据库:在关系型数据库中,也常将 JSON 字符串化后存入特定字段,便于存储半结构化或松散结构的数据。例如,在一些电商平台的数据库中,用户的个性化设置、订单的额外信息等可以存储为 JSON 字符串,以便在需要时进行灵活的查询和处理。
  2. 本地存储:浏览器提供的 localStorage 或 IndexedDB 等 API 允许以 JSON 格式存储用户数据、应用设置等,以便离线访问或持久化状态。比如,在在线文档编辑应用中,用户的文档草稿可以存储在 localStorage 中,以 JSON 格式保存,当用户下次打开应用时可以继续编辑,提高了用户的工作效率。

(三)配置文件和 RPC 远程调用

  1. 配置文件:软件开发中,JSON 常用于编写配置文件。因其清晰的结构和易读性,便于开发者管理应用程序的各项设置和参数。例如,在一个 Java 项目中,可以使用 JSON 格式的配置文件来配置数据库连接信息、日志级别等参数。相比传统的 properties 文件或 XML 配置文件,JSON 配置文件更加简洁明了,易于维护。
  2. RPC 远程调用:在微服务架构中,JSON 常用作 RPC 调用的数据交换格式,使得不同服务间能以统一、标准的方式传递复杂数据结构。例如,一个电商平台的微服务架构中,商品服务、订单服务、用户服务等不同的微服务之间可以通过 JSON 格式进行 RPC 调用,实现业务逻辑的协同工作。据统计,在微服务架构的项目中,超过 80%的团队选择 JSON 作为 RPC 调用的数据格式。

(四)移动应用

  1. JSON 在原生/混合移动应用中通过 HTTP 请求从服务器获取 JSON 数据,用于填充移动端界面。例如,新闻阅读类移动应用通过 HTTP 请求获取服务器上的新闻数据,以 JSON 格式返回,应用解析 JSON 后展示新闻标题、内容、图片等信息。在社交媒体应用中,用户的动态、好友列表等数据也以 JSON 格式从服务器获取,展示在移动端界面上。电商应用则通过 JSON 数据展示商品信息、用户购物车内容等。据市场调研显示,超过 90%的移动应用在与服务器进行数据交互时采用 JSON 格式。

四、JSON 的封装与解析

(一)各种工具包的封装示例

  1. json-lib:
    1.1. json-lib是一个用于处理JSON数据的工具包,虽然性能相对较低且长期未更新,但仍有一定的使用场景。以下是一个使用json-lib的示例代码:
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
public class JsonlibDemo {
    public static void main(String[] args) {
        String jsonContent = "{'hello':'world', 'hero':'heroine'}";
        JSONObject jsonObject = JSONObject.fromObject(jsonContent);
        String str1 = jsonObject.getString("hello");
        String str2 = jsonObject.getString("hero");
        System.out.println(str1);
        System.out.println(str2);
        System.out.println("--------------------");
        jsonContent = "[{'hello':333, 'abc': false, 'xyz': {'a': 1, 'b': 'ab'}}, " +
                "{'hello':555, 'abc': true, 'xyz': {'a': 3, 'b': 'ba'}}]";
        JSONArray jsonArray = JSONArray.fromObject(jsonContent);
        for (Object object : jsonArray) {
            JSONObject jsonObject2 = JSONObject.fromObject(object);
            int value1 = jsonObject2.getInt("hello");
            boolean value2 = jsonObject2.getBoolean("abc");
            JSONObject jsonObject3 = jsonObject2.getJSONObject("xyz");
            int value3 = jsonObject3.getInt("a");
            String value4 = jsonObject3.getString("b");
            System.out.println(value1);
            System.out.println(value2);
            System.out.println(value3);
            System.out.println(value4);
        }
    }
}
  1. 阿里巴巴 FastJson:
    2.1. FastJson是阿里巴巴开发的高性能JSON处理工具。以下是使用FastJson进行封装的示例代码:
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
public class FastJsonExample {
    public static void main(String[] args) {
        // 将对象转换为 JSON 对象
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("name", "Alice");
        jsonObject.put("age", 30);
        System.out.println(jsonObject);
        // 将数组转换为 JSON 数组
        JSONArray jsonArray = new JSONArray();
        jsonArray.add("item1");
        jsonArray.add("item2");
        System.out.println(jsonArray);
    }
}

(二)Map 和 JSON 之间的转换

  1. 使用阿里巴巴 FastJson:
    1.1. Map转JSON:
import com.alibaba.fastjson.JSONObject;
import java.util.HashMap;
import java.util.Map;
public class MapToJsonExample {
    public static void main(String[] args) {
        Map<String, Object> map = new HashMap<>();
        map.put("a", "a");
        map.put("b", "123");
        JSONObject json = new JSONObject(map);
        System.out.println(json);
    }
}

1.2. JSON转Map:

import com.alibaba.fastjson.JSONObject;
import java.util.Map;
public class JsonToMapExample {
    public static void main(String[] args) {
        JSONObject json = new JSONObject();
        json.put("ccc", "321");
        json.put("bbb", "123");
        Map<String, Object> map = (Map<String, Object>)json;
        System.out.println(map);
    }
}
  1. 使用 json-lib:
    2.1. Map转JSON:
import net.sf.json.JSONObject;
import java.util.HashMap;
import java.util.Map;
public class MapToJsonWithJsonlib {
    public static void main(String[] args) {
        Map<String, Object> map = new HashMap<>();
        map.put("name", "Bob");
        map.put("age", 25);
        JSONObject jsonObject = JSONObject.fromObject(map);
        System.out.println(jsonObject.toString());
    }
}

2.2. JSON转Map:

import net.sf.json.JSONObject;
import java.util.HashMap;
import java.util.Map;
public class JsonToMapWithJsonlib {
    public static void main(String[] args) {
        String jsonStr = "{\"name\":\"Eve\",\"age\":35}";
        JSONObject jsonObject = JSONObject.fromObject(jsonStr);
        Map<String, Object> map = (Map<String, Object>)jsonObject;
        System.out.println(map);
    }
}

(三)实体转换成 JSON

  1. 使用 Jackson:
    1.1. 首先介绍三个注解:@JsonAutoDetect (method/field):作用于方法或字段,用来表明,当生成json的时候忽略有该annotation的方法或字段;@JsonIgnore 过滤不需要转成json的属性;@JsonIgnoreProperties 主要用于过滤掉一些不需要的属性。以上三个注解需要放在get方法前面才有效。
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Transient;
import java.util.HashSet;
import java.util.Set;
@Entity
@Table(name = "menu", catalog = "zhong")
@JsonAutoDetect
public class Menu implements java.io.Serializable {
    private static final long serialVersionUID = 1L;
    private Integer id;
    private Menu menu;
    private String icon;
    private String name;
    private Short seq;
    private String url;
    private String prem;
    private Set<Menu> menus = new HashSet<Menu>(0);
    // Constructors
    public Menu() {}
    public Menu(Integer id) {
        this.id = id;
    }
    // Property accessors
    @JsonIgnore
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "pid")
    public Menu getMenu() {
        return this.menu;
    }
    public void setMenu(Menu menu) {
        this.menu = menu;
    }
    @JsonIgnore
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "menu")
    public Set<Menu> getMenus() {
        return this.menus;
    }
    public void setMenus(Set<Menu> menus) {
        this.menus = menus;
    }
    @Transient
    public String getState() {
        if (this.getMenus() == null) {
            state = "open";
        } else {
            state = "closed";
        }
        return state;
    }
    public void setState(String state) {
        this.state = state;
    }
}

1.2. 转化代码:

import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;
public class MenuConverter {
    public static void main(String[] args) {
        List<Menu> menus = menuManager.getChildrenById(aid, "pid", "seq", true);
        ObjectMapper map = new ObjectMapper();
        try {
            map.writeValue(System.out, menus);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  1. 使用反射手写实体转 JSON 的方法:
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class toJsonUtil {
    public static void main(String[] args) {
        Person test = new Person("test", 123);
        String json = toJSONString(test);
        System.out.println(json);
    }
    /**
     * 将实体类转成json 字符串
     *
     * @param bean
     * @return
     */
    public static String toJSONString(Object bean) {
        Class<?> clazz = bean.getClass();
        //获取所有字段名
        Field[] fields = clazz.getDeclaredFields();
        String json = "";
        if (fields.length > 0) {
            json += "{";
            int size = 0;
            for (Field field : fields) {
                size++;
                String name = field.getName();
                Method method = null;
                Object invoke = null;
                try {
                    //根据字段名首字母大写 拼接获取方法
                    method = clazz.getMethod("get" + name.substring(0, 1).toUpperCase() + name.substring(1), null);
                    //执行get 方法 获取字段对应的值
                    invoke = method.invoke(bean, null);
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
                //拼接成json 格式的字符串
                if (size < fields.length) {
                    json += "'" + name + "':'" + invoke.toString() + "',";
                } else {
                    json += "'" + name + "':'" + invoke.toString() + "'";
                }
            }
            json += "}";
        }
        return json;
    }
}
class Person {
    String name;
    int age;
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    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;
    }
}

(四)JSON 的解析方法

  1. 使用 json-lib:
    1.1. json-lib的XMLSerializer的read使用,json-lib的xml必须有一个对象obj(Object)节点包含里面的节点。
import net.sf.json.JSONArray;
import net.sf.json.xml.XMLSerializer;
public class JsonXMLSerializer {
    public static void main(String[] args) {
        String xml = "";
        xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                "<obj>" +
                "<stu type=\"string\">令狐冲</stu>" +
                "<stu type=\"string\">东升布艺</stu>" +
                "<stu type=\"string\">周伯通</stu>" +
                "</obj>";
        XMLSerializer serializer = new XMLSerializer();
        JSONArray jarr = (JSONArray) serializer.read(xml);
        for (int i = 0; i < jarr.size(); i++) {
            System.out.println(jarr.get(i));
        }
    }
}
  1. 使用阿里巴巴 FastJson:
    2.1. 将存储在数据库中的Json格式的字符串转化为Java对象(List),最终使用了JSONArray.parseObject(String text, TypeReference type, Feature… features)这个静态方法将String类型的JSON串转化为JAVA对象。
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.TypeReference;
import java.util.List;
public class FastJsonParseExample {
    public static void main(String[] args) {
        String jsonStr = "[{'name':'Alice','age':30},{'name':'Bob','age':25}]";
        List<Person> people = JSONArray.parseObject(jsonStr, new TypeReference<List<Person>>() {});
        for (Person person : people) {
            System.out.println(person.getName() + " " + person.getAge());
        }
    }
}
class Person {
    private String name;
    private int age;
    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;
    }
}

五、json-server 全攻略

(一)准备工作

JSON-server 是一个基于 Node.js 的模拟 RESTful API 的工具,可以快速搭建一个后端服务器,用于开发和测试前端应用。在使用 JSON-server 之前,需要先安装 Node.js。

  1. 安装 Node.js:可以从 Node.js 官方网站下载安装包,按照安装向导进行安装。安装完成后,可以在命令行中输入 node -v 和 npm -v 来检查 Node.js 和 npm 的版本。
  2. 全局安装 json-server:在命令行中输入 npm install -g json-server 来全局安装 json-server。安装完成后,可以在命令行中输入 json-server -v 来查看 json-server 的版本。
  3. 准备 JSON 文件:创建一个 JSON 文件,用于存储数据。例如,可以创建一个名为 db.json 的文件,内容如下:
{
  "posts": [
    { "id": 1, "title": "json-server", "author": "typicode" }
  ],
  "comments": [
    { "id": 1, "body": "some comment", "postId": 1 }
  ],
  "profile": { "name": "typicode" }
}

(二)启动服务

  1. 常用命令选项:
    1.1. json-server --watch db.json:启动 json-server,监视 db.json 文件的变化。
    1.2. json-server --port 3001 --watch db.json:启动 json-server,监视 db.json 文件的变化,并指定端口号为 3001。
    1.3. json-server --host 0.0.0.0 --watch db.json --port 3001:启动 json-server,监视 db.json 文件的变化,并指定端口号为 3001,允许外部访问。
  2. 工作场景建议:
    2.1. 开发环境:在开发环境中,可以使用 json-server --watch db.json 来启动 json-server,监视 db.json 文件的变化,方便开发和调试。
    2.2. 测试环境:在测试环境中,可以使用 json-server --host 0.0.0.0 --watch db.json --port 3001 来启动 json-server,监视 db.json 文件的变化,并指定端口号为 3001,允许外部访问,方便测试人员进行测试。
  3. 通过 package.json 文件启动项目:
    3.1. 在 package.json 文件中添加一个脚本,例如:
"scripts": {
  "start": "json-server --watch db.json"
}

3.2. 在命令行中输入 npm start 来启动 json-server。
4. 自定义配置文件启动项目:
4.1. 创建一个名为 json-server.config.json 的文件,内容如下:

{
  "port": 3001,
  "watch": true,
  "static": "./public",
  "read-only": false,
  "no-cors": false,
  "no-gzip": false
}

4.2. 在命令行中输入 json-server --config json-server.config.json 来启动 json-server。

(三)获取数据

  1. 通过 get 获取 scoreList 属性:
    1.1. 假设我们的 JSON 文件中有一个名为 scoreList 的属性,我们可以通过以下方式获取这个属性的值:
http://localhost:3000/scoreList
  1. 单条件查找:
    2.1. 假设我们的 JSON 文件中有一个名为 students 的属性,我们可以通过以下方式查找 students 属性中 id 为 1 的学生:
http://localhost:3000/students?id=1
  1. 多条件查找:
    3.1. 假设我们的 JSON 文件中有一个名为 students 的属性,我们可以通过以下方式查找 students 属性中 id 为 1 且 name 为 Alice 的学生:
http://localhost:3000/students?id=1&name=Alice
  1. 全局搜索:
    4.1. 假设我们的 JSON 文件中有一个名为 students 的属性,我们可以通过以下方式全局搜索 name 中包含 Alice 的学生:
http://localhost:3000/students?q=Alice
  1. 分页查询:
    5.1. 假设我们的 JSON 文件中有一个名为 students 的属性,我们可以通过以下方式分页查询 students 属性中的学生:
http://localhost:3000/students?_page=1&_limit=10

六、Python 中的 JSON 操作

(一)json 相关方法及用法

在 Python 中,json模块提供了一系列方法用于处理 JSON 数据。
json.dumps()是把 Python 对象转换成 JSON 对象的一个过程,生成的是字符串。例如:

import json
data = {'token':'e5dads5 3455s2','verify':True,'content':'中文'}
data_json = json.dumps(data)
print(data_json)
# 输出:{"token": "e5dads5 3455s2", "verify": true, "content": "\\u4e2d\\u6587"}

可以通过携带参数来调整输出。比如设置ensure_ascii=False可以正常显示中文:

data_json = json.dumps(data,ensure_ascii=False)
print(data_json)
# 输出:{"token": "e5dads5 3455s2", "verify": true, "content": "中文"}

设置separators=(‘,’,‘:’)可以去掉,和:后面的空格:

data_json = json.dumps(data,separators=(',',':'))
print(data_json)
# 输出:{"token":"e5dads5 3455s2","verify":true,"content":"中文"}

json.loads()用于将 JSON 格式的字符串转换为 Python 对象。例如:

j_dict = '{"name": "张三", "info": {"family": ["father", "mother"], "age": 18}, "score": 87.5, "skill": "eat"}'
dict1 = json.loads(j_dict)
print(dict1)
print(type(dict1))

json.dump()是把 Python 对象转换成 JSON 对象生成一个文件流,和文件相关。例如:

import json
data = {'name':'John','age':30,'city':'New York'}
with open('data.json','w') as f:
    json.dump(data, f)

json.load()从文件中读取 JSON 数据并将其解析为 Python 对象。例如:

import json
with open('data.json', 'r') as f:
    data = json.load(f)

(二)使用正则抓取数据案例

下面通过一个案例展示如何使用正则表达式抓取数据并封装成面向对象。
假设我们要从网页中抓取一些特定格式的数据,比如从一个包含段子的网页中抓取所有的段子内容。
首先,我们可以定义一个类来处理网页请求和数据筛选。以下是一个示例代码:

import requests
import re
class Spider:
    def loadPage(self, page):
        url = f'http://www.neihan8.com/article/list_5_{page}.html'
        html = requests.get(url).text
        # 处理中文编码问题
        return html.decode('gbk')
    def printOnePage(self, item_list):
        for item in item_list:
            # 去除不需要的标签
            item = re.sub(r'<p>', '', item)
            item = re.sub(r'</p>', '', item)
            print(item)
    def getContent(self, page):
        gbk_html = self.loadPage(page)
        # 使用正则表达式筛选数据
        item_list = re.findall(r'<div.*?class="f18 mb20">(.*?)</div>', gbk_html, re.S)
        self.printOnePage(item_list)

使用这个类可以这样调用:

spider = Spider()
spider.getContent(1)

在这个例子中,我们首先定义了一个Spider类,其中loadPage方法用于加载指定页面的内容,printOnePage方法用于打印筛选后的内容,getContent方法用于获取指定页面的内容并进行筛选和打印。通过使用正则表达式’<div.?class=“f18 mb20”>(.?)',我们可以匹配到网页中所有

之间的数据,即我们需要的段子内容。然后,我们通过去除

标签来清理数据,最后打印出每个段子。
这个案例展示了如何使用正则表达式在 Python 中抓取特定格式的数据,并将其封装成面向对象的形式,以便更好地组织和管理代码。

七、JSON 的优缺点

(一)优点

JSON 作为一种轻量级的数据交换格式,具有诸多优点:

  1. 灵巧的数据传输格式:JSON 与 XML 很相似,但更加灵巧。XML 需要更多的标记和结构,而 JSON 的格式更加简洁,数据量相对较小,传输效率更高。例如,在一个简单的用户信息传输场景中,JSON 可以用{“name”:“John”,“age”:30}这样简洁的格式表示,而 XML 可能需要更多的标签和属性来达到相同的效果。
  2. 无需特定内容类型首部信息:JSON 不需要从服务器端发送含有特定内容类型的首部信息,这使得数据传输更加高效和简洁。在网络通信中,减少了不必要的头部信息可以降低网络开销,提高传输速度。
  3. 兼容性广泛:JSON 的格式是文本格式,不依赖于任何特定的平台或语言,可以在不同的编程语言和操作系统之间进行数据交换。几乎所有的现代编程语言都有对 JSON 的支持,这使得 JSON 在跨平台、跨语言的应用开发中非常方便。例如,一个用 Java 开发的服务器端可以轻松地将数据以 JSON 格式发送给用 JavaScript 开发的客户端,而无需进行复杂的格式转换。
  4. 共享数据方便:JSON 格式的数据易于读写,格式经过压缩,占用带宽小。在网络传输中,这意味着可以更快地传输数据,节省流量。同时,JSON 的结构清晰,易于理解,方便开发人员进行数据的读取和处理。例如,在一个移动应用中,通过 HTTP 请求从服务器获取 JSON 数据,可以快速地填充移动端界面,展示用户所需的信息。
  5. 服务器端解析快:JSON 可以在服务器上快速解析。在服务器端解析是开发人员关注的重要部分,如果解析在服务器端快速,那么用户可以得到快速响应。例如,在一个高并发的 Web 应用中,服务器需要快速处理大量的请求,如果使用 JSON 作为数据格式,可以减少解析时间,提高服务器的响应速度。
    此外,JSON 还有一些其他优点:
  6. 易于阅读和编写:JSON 的语法非常简单易懂,与 JavaScript 的语法非常相似,使得开发者很容易读懂和编写 JSON 格式的数据。例如,一个包含用户信息的 JSON 对象可以用{“name”:“Alice”,“age”:25,“address”:{“city”:“New York”,“country”:“USA”}}这样直观的方式表示,开发人员可以轻松地理解和修改其中的数据。
  7. 支持多种语言:JSON 支持多种语言,包括 C、C++、PHP、Python、Ruby 等。这使得不同语言的开发团队可以轻松地使用 JSON 进行数据交换。例如,一个由多种语言开发的微服务架构中,不同的服务可以通过 JSON 格式进行 RPC 调用,实现业务逻辑的协同工作。

(二)缺点

尽管 JSON 有很多优点,但它也存在一些缺点:

  1. 缺乏错误处理机制:JSON 本身没有内置的错误处理机制。如果在数据传输过程中出现错误,例如数据格式不正确或缺失关键字段,接收方可能需要进行额外的错误处理。这增加了开发的复杂性,特别是在处理大量数据或复杂数据结构时。例如,一个 JSON 对象中缺少了必填字段,接收方需要检查每个字段是否存在,并进行相应的错误处理。
  2. 安全风险:当与不受信任的服务或浏览器一起使用时,JSON 可能存在安全风险。恶意用户可能会构造恶意的 JSON 数据,通过 JSON 注入攻击实现对网站的攻击。例如,攻击者可以在 JSON 数据中插入恶意脚本,当接收方解析 JSON 时,恶意脚本可能会被执行,导致安全漏洞。此外,“顶级 JSON 数组”也存在安全风险,因为服务器端可能无法正确地解析和过滤其中的每个元素,从而导致安全漏洞。
  3. 支持工具相对有限:与一些成熟的数据格式相比,JSON 的支持工具相对有限。虽然有很多库和框架支持 JSON 的处理,但在某些特定的领域或复杂的应用场景中,可能需要更多的工具和功能。例如,在处理大型二进制数据时,JSON 不如专门的二进制格式高效;在处理复杂的数据关系时,JSON 缺乏引用和循环引用的支持,可能导致数据冗余和难以维护。
    综上所述,JSON 作为一种轻量级的数据交换格式,在很多场景下都表现出色,但也需要注意其缺点,在使用过程中采取相应的措施来避免潜在的问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奔跑吧邓邓子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值