json和jsonpath

什么是JSON

JSON是比XML更简单的一种数据交换格式,它采用完全独立于编程语言的文本格式来存储和表示数据。

语法

使用键值对(key:value)表示对象的属性

使用逗号(,)分隔多条数据

使用花括号{ }表示对象

使用方括号[ ]表示数组

JSON键/值对

格式是:字段名称(包含在双引号中),后面加一个冒号,然后是值。

例如:"name": "XiaoHong"

JSON的值

数字(整数或浮点数)、字符串(在双引号中)、逻辑值(true 或 false)、数组(在方括号中)、对象(在花括号中)、null

JSON对象

对象表示为花括号{ }括起来的内容,数据结构为 { key:value, key:value, ... }的键值对的结构。

例如:{"name": "XiaoHong", "age":18}

JSON数组

数组表示为中括号[ ]括起来的内容,数据结构为 [字段1, 字段2, 字段3, ...],其中字段值的类型可以是数字、字符串、数组、对象几种。

例如: ["Python", "javascript", "C++", ...]

JSON vs XML

JSON的语法格式简单,层次结构清晰,比XML更易于阅读。另外,由于它占用的字符量少,用于网络数据传输时,能节约带宽,提高了传输效率。

JSON模块使用

json模块提供了Python对象的序列化和反序列化功能。

序列化:将一个Python对象编码转换为JSON字符串的过程。

反序列化:将JSON字符串解码转换为Python对象的过程。

1)无需安装,直接使用import json导入即可

2)四个方法:dumps、dump、loads、load,用于字符串和Python数据类型间进行转换。

其中,loads和load方法用于Python对象的反序列化,dumps和dump方法用于Python对象的序列化。

json.loads()方法 JSON格式字符串=>Python对象

|--------------|------------|
| JSON | Python |
| object | dict |
| array | list |
| string | unicode |
| number(int) | int,long |
| number(real) | float |
| true | True |
| false | False |
| null | None |

json.dumps()方法 Python对象=>JSON字符串 返回一个str对象。

|----------------|----------|
| Python | JSON |
| dict | object |
| list,tuple | array |
| str, unicode | string |
| int,long,float | number |
| True | true |
| False | false |
| None | null |

案例1:JSON字符串格式与Python对象的转换

python 复制代码
import json
json_str = '{"name": "jack","age": 18}'

"""1. JSON字符串格式与Python对象的转换"""
print("=" * 60)
print("1. JSON字符串格式与Python对象的转换")
print("=" * 60)

# Python对象转JSON字符串 (序列化)
python_dict = {
    "name": "张三",
    "age": 25,
    "city": "北京",
    "hobbies": ["读书", "游泳", "编程"],
    "is_student": False,
    "score": None
}

# dumps: dict -> str
json_str = json.dumps(python_dict, ensure_ascii=False, indent=4)
print("Python字典转JSON字符串:")
print(json_str)
print()

# JSON字符串转Python对象 (反序列化)
json_string = '{"name": "李四", "age": 30, "city": "上海","is_student": false,"score": null}'
# loads: str -> dict
python_obj = json.loads(json_string)
print("JSON字符串转Python字典:")
print(f"类型: {type(python_obj)}, 内容: {python_obj}")
print()

# 其他Python对象转换
python_list = [1, 2, 3, "test", True, None]
json_from_list = json.dumps(python_list, ensure_ascii=False)
print(f"列表转JSON: {json_from_list}")

back_to_list = json.loads(json_from_list)
print(f"JSON转回列表: {back_to_list}")
print()

案例2:JSON文件格式的导入与导出

python 复制代码
import json

"""2. JSON文件格式的导入与导出"""
print("=" * 60)
print("2. JSON文件格式的导入与导出")
print("=" * 60)

# 准备数据
data = {
    "employees": [
        {"id": 1, "name": "张三", "department": "技术部", "salary": 15000},
        {"id": 2, "name": "李四", "department": "市场部", "salary": 12000},
        {"id": 3, "name": "王五", "department": "技术部", "salary": 18000},
        {"id": 4, "name": "赵六", "department": "人事部", "salary": 11000}
    ],
    "company": "示例公司",
    "year": 2026
}

# 导出JSON到文件
filename = "data.json"
with open(filename, 'w', encoding='utf-8') as f:
    # dump: dict -> file
    json.dump(data, f, ensure_ascii=False, indent=2)
print(f"数据已导出到 {filename}")
print()

# 从文件导入JSON
with open(filename, 'r', encoding='utf-8') as f:
    # load: file -> dict
    loaded_data = json.load(f)
print(f"从 {filename} 加载的数据:")
print(f"公司名称: {loaded_data['company']}")
print(f"员工数量: {len(loaded_data['employees'])}")
print(f"第一个员工: {loaded_data['employees'][0]['name']}")
print()

什么是JSONPath

JSONPATH的语法

JSONPath是一种信息抽取类库,是从JSON文档中抽取指定信息的工具,提供多种语言实现版本,包括:Javascript,Python,PHP和Java。

JSONPath的安装方法:pip install jsonpath -i https://mirrors.aliyun.com/pypi/simple/

JSON语法(对比XPath)

|-----------|--------------|----------------------------------------------|
| XPath | JSONPath | 描述 |
| / | $ | 根节点 |
| . | @ | 当前节点 |
| / | .or[] | 取子节点 |
| .. | 不支持 | 取父节点,JSONPath未支持 |
| // | .. | 就是不管位置,选择所有符合条件的节点 |
| * | * | 匹配所有元素节点 |
| @ | 不支持 | 根据属性访问,JSON不支持,因为JSON是个key-value递归结构,不需要属性访问 |
| [] | [] | 迭代器标示(可以在里边做简单的迭代操作,如数组下标,根据内容选值等) |
| | | [,] | 支持迭代器中做多选,并集 |
| [] | ?() | 支持过滤操作 |
| 不支持 | () | 支持表达式计算 |
| () | 不支持 | 分组,JSONPath不支持 |

案例3:JSONPath语法提取信息 - 基础

python 复制代码
import json
import jsonpath
"""3. JSONPath语法提取信息 - 基础"""
print("=" * 60)
print("3. JSONPath语法提取信息")
print("=" * 60)

# 测试数据
data = {
    "store": {
        "book": [
            {
                "category": None,
                "author": "Nigel Rees",
                "title": "Sayings of the Century",
                "price": 8.95
            },
            {
                "category": "小说",
                "author": " Evelyn Waugh",
                "title": "Sword of Honour",
                "price": 12.99
            },
            {
                "category": "小说",
                "author": "Herman Melville",
                "title": "Moby Dick",
                "isbn": "0-553-21311-3",
                "price": 8.99
            },
            {
                "category": "小说",
                "author": "J. R. R. Tolkien",
                "title": "The Lord of the Rings",
                "isbn": "0-395-19395-8",
                "price": 22.99
            }
        ],
        "bicycle": {
            "color": "红色",
            "price": 19.95
        }
    }
}

print("测试数据结构:")
print(json.dumps(data, ensure_ascii=False, indent=2))
print(data)
print()

# 根节点与子节点处理
print("【根节点与子节点】")
# $ 表示根节点
# 修改后 - 添加错误检查
result = jsonpath.jsonpath(data, '$')
if result is False:
    print("JSONPath 匹配失败,请检查数据和表达式")
else:
    print(f"$ (根节点): {type(result)}, 内容: {result}")

# . 或 [] 访问子节点
result = jsonpath.jsonpath(data, '$.store')
print(f"$.store (store对象): {result}")

result = jsonpath.jsonpath(data, '$.store.bicycle')
print(f"$.store.bicycle (自行车信息): {result[0]['color']}")
print()

# 元素匹配与列表下标
print("【元素匹配与列表下标】")
# 获取所有书籍
result = jsonpath.jsonpath(data, '$.store.book.*')
print(f"$.store.book[*] (所有书籍): 共{len(result)}本")

# 获取第一本书
result = jsonpath.jsonpath(data, '$.store.book[0]')
print(result)
print(f"$.store.book[0] (第一本书): {result[0]['title']}")

# 获取最后一本书
result = jsonpath.jsonpath(data, '$.store.book[-1:]')
print(f"$.store.book[-1:] (最后一本书): {result[0]['title']}")

# 获取前两本书
result = jsonpath.jsonpath(data, '$.store.book[0:2]')
print(f"$.store.book[0:2] (前两本书): {[book['title'] for book in result]}")

# 获取所有书名
result = jsonpath.jsonpath(data, '$.store.book[*].title')
print(f"$.store.book[*].title (所有书名): {result}")

# 获取所有价格
result = jsonpath.jsonpath(data, '$..price')
print(f"$..price (所有价格): {result}")
print()

# 过滤条件
print("【过滤条件】")
# 过滤价格小于10的书籍
result = jsonpath.jsonpath(data, '$.store.book[?(@.price<10)]')
print(result)
print(f"价格<10的书籍: {[book['title'] for book in result]}")

# 过滤类别为"小说"的书籍
result = jsonpath.jsonpath(data, '$.store.book[?(@.category=="小说")]')
print(f"类别为'小说'的书籍: {[book['title'] for book in result]}")

# 过滤有ISBN的书籍
result = jsonpath.jsonpath(data, '$.store.book[?(@.isbn)]')
print(f"有ISBN的书籍: {[book['title'] for book in result]}")

# 递归搜索所有作者
result = jsonpath.jsonpath(data, '$..author')
print(f"$..author (所有作者): {result}")
print()

综合以上案例并深化

python 复制代码
import json
import jsonpath


def demo_json_conversion():
    """1. JSON字符串格式与Python对象的转换"""
    print("=" * 60)
    print("1. JSON字符串格式与Python对象的转换")
    print("=" * 60)

    # Python对象转JSON字符串 (序列化)
    python_dict = {
        "name": "张三",
        "age": 25,
        "city": "北京",
        "hobbies": ["读书", "游泳", "编程"],
        "is_student": False,
        "score": None
    }

    # dumps: dict -> str
    json_str = json.dumps(python_dict, ensure_ascii=False, indent=4)
    print("Python字典转JSON字符串:")
    print(json_str)
    print()

    # JSON字符串转Python对象 (反序列化)
    json_string = '{"name": "李四", "age": 30, "city": "上海","is_student": false,"score": null}'
    # loads: str -> dict
    python_obj = json.loads(json_string)
    print("JSON字符串转Python字典:")
    print(f"类型: {type(python_obj)}, 内容: {python_obj}")
    print()

    # 其他Python对象转换
    python_list = [1, 2, 3, "test", True, None]
    json_from_list = json.dumps(python_list, ensure_ascii=False)
    print(f"列表转JSON: {json_from_list}")

    back_to_list = json.loads(json_from_list)
    print(f"JSON转回列表: {back_to_list}")
    print()


def demo_json_file_io():
    """2. JSON文件格式的导入与导出"""
    print("=" * 60)
    print("2. JSON文件格式的导入与导出")
    print("=" * 60)

    # 准备数据
    data = {
        "employees": [
            {"id": 1, "name": "张三", "department": "技术部", "salary": 15000},
            {"id": 2, "name": "李四", "department": "市场部", "salary": 12000},
            {"id": 3, "name": "王五", "department": "技术部", "salary": 18000},
            {"id": 4, "name": "赵六", "department": "人事部", "salary": 11000}
        ],
        "company": "示例公司",
        "year": 2026
    }

    # 导出JSON到文件
    filename = "data.json"
    with open(filename, 'w', encoding='utf-8') as f:
        # dump: dict -> file
        json.dump(data, f, ensure_ascii=False, indent=2)
    print(f"数据已导出到 {filename}")
    print()

    # 从文件导入JSON
    with open(filename, 'r', encoding='utf-8') as f:
        # load: file -> dict
        loaded_data = json.load(f)
    print(f"从 {filename} 加载的数据:")
    print(f"公司名称: {loaded_data['company']}")
    print(f"员工数量: {len(loaded_data['employees'])}")
    print(f"第一个员工: {loaded_data['employees'][0]['name']}")
    print()


def demo_jsonpath_basic():
    """3. JSONPath语法提取信息 - 基础"""
    print("=" * 60)
    print("3. JSONPath语法提取信息")
    print("=" * 60)

    # 测试数据
    data = {
        "store": {
            "book": [
                {
                    "category": None,
                    "author": "Nigel Rees",
                    "title": "Sayings of the Century",
                    "price": 8.95
                },
                {
                    "category": "小说",
                    "author": " Evelyn Waugh",
                    "title": "Sword of Honour",
                    "price": 12.99
                },
                {
                    "category": "小说",
                    "author": "Herman Melville",
                    "title": "Moby Dick",
                    "isbn": "0-553-21311-3",
                    "price": 8.99
                },
                {
                    "category": "小说",
                    "author": "J. R. R. Tolkien",
                    "title": "The Lord of the Rings",
                    "isbn": "0-395-19395-8",
                    "price": 22.99
                }
            ],
            "bicycle": {
                "color": "红色",
                "price": 19.95
            }
        }
    }

    print("测试数据结构:")
    print(json.dumps(data, ensure_ascii=False, indent=2))
    print(data)
    print()

    # 根节点与子节点处理
    print("【根节点与子节点】")
    # $ 表示根节点
    # 修改后 - 添加错误检查
    result = jsonpath.jsonpath(data, '$')
    if result is False:
        print("JSONPath 匹配失败,请检查数据和表达式")
    else:
        print(f"$ (根节点): {type(result)}, 内容: {result}")

    # . 或 [] 访问子节点
    result = jsonpath.jsonpath(data, '$.store')
    print(f"$.store (store对象): {result}")

    result = jsonpath.jsonpath(data, '$.store.bicycle')
    print(f"$.store.bicycle (自行车信息): {result[0]}")
    print()

    # 元素匹配与列表下标
    print("【元素匹配与列表下标】")
    # 获取所有书籍
    result = jsonpath.jsonpath(data, '$.store.book.*')
    print(f"$.store.book[*] (所有书籍): 共{len(result)}本")

    # 获取第一本书
    result = jsonpath.jsonpath(data, '$.store.book[0]')
    print(result)
    print(f"$.store.book[0] (第一本书): {result[0]['title']}")

    # 获取最后一本书
    result = jsonpath.jsonpath(data, '$.store.book[-1:]')
    print(f"$.store.book[-1:] (最后一本书): {result[0]['title']}")

    # 获取前两本书
    result = jsonpath.jsonpath(data, '$.store.book[0:2]')
    print(f"$.store.book[0:2] (前两本书): {[book['title'] for book in result]}")

    # 获取所有书名
    result = jsonpath.jsonpath(data, '$.store.book[*].title')
    print(f"$.store.book[*].title (所有书名): {result}")

    # 获取所有价格
    result = jsonpath.jsonpath(data, '$..price')
    print(f"$..price (所有价格): {result}")
    print()

    # 过滤条件
    print("【过滤条件】")
    # 过滤价格小于10的书籍
    result = jsonpath.jsonpath(data, '$.store.book[?(@.price<10)]')
    print(f"价格<10的书籍: {[book['title'] for book in result]}")

    # 过滤类别为"小说"的书籍
    result = jsonpath.jsonpath(data, '$.store.book[?(@.category=="小说")]')
    print(f"类别为'小说'的书籍: {[book['title'] for book in result]}")

    # 过滤有ISBN的书籍
    result = jsonpath.jsonpath(data, '$.store.book[?(@.isbn)]')
    print(f"有ISBN的书籍: {[book['title'] for book in result]}")

    # 递归搜索所有作者
    result = jsonpath.jsonpath(data, '$..author')
    print(f"$..author (所有作者): {result}")
    print()


def demo_jsonpath_advanced():
    """JSONPath高级用法"""
    print("=" * 60)
    print("4. JSONPath高级用法")
    print("=" * 60)

    data = {
        "users": [
            {"id": 1, "name": "张三", "age": 26, "city": "北京", "scores": [90, 85, 92]},
            {"id": 2, "name": "李四", "age": 30, "city": "上海", "scores": [78, 88, 95]},
            {"id": 3, "name": "王五", "age": 28, "city": "北京", "scores": [92, 91, 89]},
            {"id": 4, "name": "赵六", "age": 35, "city": "广州", "scores": [85, 80, 82]},
            {"id": 5, "name": "钱七", "age": 22, "city": "上海", "scores": [95, 93, 97]}
        ]
    }

    print("【多条件过滤】")
    # 北京的且年龄大于25的用户
    result = jsonpath.jsonpath(data, '$.users[?(@.city=="北京" & @.age>25)]')
    print(f"北京且年龄>25: {result}")
    # print(f"北京且年龄>25: {[user['name'] for user in result]}")

    # 上海的或年龄小于25的用户
    result = jsonpath.jsonpath(data, '$.users[?(@.city=="上海" | @.age<25)]')
    # print(f"上海或年龄<25: {[user['name'] for user in result]}")

    print()
    print("【数组索引高级用法】")
    # 获取前3个用户
    result = jsonpath.jsonpath(data, '$.users[0:3]')
    print(f"前3个用户: {[user['name'] for user in result]}")

    # 获取最后2个用户
    result = jsonpath.jsonpath(data, '$.users[-2:]')
    print(f"最后2个用户: {[user['name'] for user in result]}")

    # 获取特定索引的用户 (第1和第3个)
    result = jsonpath.jsonpath(data, '$.users[0,2]')
    print(f"第1和第3个用户: {[user['name'] for user in result]}")

    print()
    print("【嵌套数据访问】")
    # 获取所有用户的第二个分数
    result = jsonpath.jsonpath(data, '$.users[*].scores[1]')
    print(f"所有用户的第二个分数: {result}")

    # 获取第一个用户的所有分数
    result = jsonpath.jsonpath(data, '$.users[0].scores[*]')
    print(f"第一个用户的所有分数: {result}")

    print()
    print("【通配符使用】")
    # 获取所有用户的所有信息
    result = jsonpath.jsonpath(data, '$.users[*][*]')
    print(f"所有用户的所有属性值 (扁平化): {result[:10]}...")  # 只显示前10个

    # 递归查找所有score相关
    result = jsonpath.jsonpath(data, '$..scores')
    print(f"所有scores数组: {result}")


def demo_practical_example():
    """实际应用示例"""
    print("=" * 60)
    print("5. 实际应用示例")
    print("=" * 60)

    # 模拟API返回的数据
    api_response = {
        "code": 200,
        "message": "success",
        "data": {
            "total": 5,
            "items": [
                {"product_id": "P001", "name": "笔记本电脑", "price": 5999, "stock": 50, "category": "电子产品"},
                {"product_id": "P002", "name": "鼠标", "price": 99, "stock": 200, "category": "配件"},
                {"product_id": "P003", "name": "键盘", "price": 299, "stock": 150, "category": "配件"},
                {"product_id": "P004", "name": "显示器", "price": 1999, "stock": 30, "category": "电子产品"},
                {"product_id": "P005", "name": "耳机", "price": 399, "stock": 0, "category": "配件"}
            ]
        }
    }

    # 保存到文件
    with open('api_response.json', 'w', encoding='utf-8') as f:
        json.dump(api_response, f, ensure_ascii=False, indent=2)
    print("API响应数据已保存到 api_response.json")
    print()

    # 从文件读取
    with open('api_response.json', 'r', encoding='utf-8') as f:
        response = json.load(f)

    print("【数据提取示例】")
    # 检查响应状态
    code = jsonpath.jsonpath(response, '$.code')[0]
    message = jsonpath.jsonpath(response, '$.message')[0]
    print(f"响应状态: {code}, 消息: {message}")

    # 获取商品总数
    total = jsonpath.jsonpath(response, '$.data.total')[0]
    print(f"商品总数: {total}")

    # 获取所有商品名称
    names = jsonpath.jsonpath(response, '$.data.items[*].name')
    print(f"所有商品: {names}")

    # 获取有库存的商品
    in_stock = jsonpath.jsonpath(response, '$.data.items[?(@.stock>0)]')
    print(f"有库存的商品: {[item['name'] for item in in_stock]}")

    # 获取缺货商品
    out_of_stock = jsonpath.jsonpath(response, '$.data.items[?(@.stock==0)]')
    print(f"缺货商品: {[item['name'] for item in out_of_stock]}")

    # 获取电子产品类别的商品
    electronics = jsonpath.jsonpath(response, '$.data.items[?(@.category=="电子产品")]')
    print(f"电子产品: {[item['name'] for item in electronics]}")

    # 获取价格大于500的商品
    expensive = jsonpath.jsonpath(response, '$.data.items[?(@.price>500)]')
    print(f"价格>500的商品: {[item['name'] for item in expensive]}")

    # 计算平均价格
    prices = jsonpath.jsonpath(response, '$.data.items[*].price')
    avg_price = sum(prices) / len(prices)
    print(f"平均价格: {avg_price:.2f}")

    print()
    print("【数据修改与保存】")
    # 修改数据 - 给缺货商品补货
    for item in response['data']['items']:
        if item['stock'] == 0:
            item['stock'] = 100
            print(f"{item['name']} 已补货至 100 件")

    # 保存修改后的数据
    with open('api_response_updated.json', 'w', encoding='utf-8') as f:
        json.dump(response, f, ensure_ascii=False, indent=2)
    print("更新后的数据已保存到 api_response_updated.json")


if __name__ == '__main__':
    # 运行所有示例
    #demo_json_conversion()
    #demo_json_file_io()
    demo_jsonpath_basic()
    # demo_jsonpath_advanced()
    # demo_practical_example()

    print("\n" + "=" * 60)
    print("所有示例执行完成!")
    print("=" * 60)
相关推荐
lg_cool_2 小时前
Python 框架之py_trees
开发语言·数据结构·python
维基框架2 小时前
WIKI 知识库 v1.0.0 正式发布
python
tlwlmy2 小时前
购物团截图自动马赛克地址,手机号码
python
断眉的派大星2 小时前
PyTorch 计算图与自动求导机制(超通俗精讲)
人工智能·pytorch·python
梦因you而美2 小时前
Python win32com 复制Excel sheet优化:覆盖替换而非删除重建,彻底解决公式报错
python·excel·win32com·python自动化·批量复制sheet表
SunnyDays10112 小时前
Python 如何实现 Markdown 与 Excel 互转
python·excel转markdown·markdown转excel·markdown转xlsx
我的xiaodoujiao2 小时前
API 接口自动化测试详细图文教程学习系列10--Requests模块2--举例说明
python·学习·测试工具·pytest
嵌入式-小王2 小时前
LangChain框架(二)---- 提示词模板
python·langchain
克里普crirp2 小时前
北斗电离层模型BDGIM广播系数
开发语言·python