python json
### Python JSON不只是数据交换那么简单1. 他是什么JSON的全称是JavaScript Object Notation但别被名字骗了它早已成为一种语言无关的数据格式。想象一下你写了一份购物清单用文本记录下“苹果、牛奶、面包”这其实就是一种简单的数据表达方式。JSON做的类似只不过它有一套固定的规则——用大括号表示对象用方括号表示数组用冒号连接键和值。比如{name: Alice, age: 30}一眼就能看出这是一个人的信息。Python中的json模块是标准库的一部分不需要额外安装。它的核心任务就是把这种文本格式和Python的数据结构比如字典、列表之间做相互转换。很多初学者会混淆“JSON字符串”和“Python字典”其实前者是字符串后者是内存中的对象。比如{name: Alice}是一个字符串而{name: Alice}才是字典。json模块就是连接这两者的桥梁。2. 他能做什么JSON最常见的用途是网络数据传输。当你用浏览器打开一个网站后台返回的数据如果是JSON格式浏览器就能轻松解读并渲染成页面。比如从天气API获取数据返回的可能是{temp: 25, humidity: 80}Python程序拿到后直接解析成字典就能提取温度值。但它的能力远不止于此。很多配置文件比如VSCode的settings.json就是JSON格式因为它比XML更简洁比YAML更严格比如不允许缩进错误。Python中也可以用JSON保存程序状态——比如游戏进度、用户偏好甚至做一个简单的键值数据库。记得有一次写一个爬虫需要暂停后再恢复我把爬取过的URL存成JSON文件重启后直接读取省去了重复爬取的麻烦。JSON的另一个奇妙用途是跨语言通信。比如一个系统用Java写后端另一个用Python做数据分析两者用JSON交换数据就像两个人用同一种语言聊天各取所需。Python的json模块天生支持Unicode处理中文时也很稳——只要确保ensure_asciiFalse中文就不会被转成\uXXXX形式。3. 怎么使用用Python处理JSON基本就是四个函数json.dumps字典转字符串、json.loads字符串转字典、json.dump字典写入文件、json.load从文件读取字典。举个例子importjson# 字典转字符串data{name:Alice,age:30}json_strjson.dumps(data,indent2,ensure_asciiFalse)print(json_str)# 输出格式化的字符串# 字符串转字典json_str{name: Bob, age: 25}datajson.loads(json_str)print(data[name])# 输出 Bob# 写入文件withopen(data.json,w,encodingutf-8)asf:json.dump(data,f,indent2,ensure_asciiFalse)# 读取文件withopen(data.json,r,encodingutf-8)asf:datajson.load(f)注意几点dumps和dump的区别类似于str()和写入文件的区别indent参数是让输出可读的关键生产环境里经常设为2或4ensure_asciiFalse必须加否则中文会变成乱码。还有load和loads——前者从文件对象读后者从字符串读名字里的s代表string很好记。处理复杂数据类型时JSON的局限性就暴露了。比如Python的datetime对象、集合、甚至简单的元组JSON原生不支持。一种做法是写自定义编码器比如把datetime转成ISO格式字符串fromdatetimeimportdatetimeclassCustomEncoder(json.JSONEncoder):defdefault(self,obj):ifisinstance(obj,datetime):returnobj.isoformat()returnsuper().default(obj)data{time:datetime.now()}json_strjson.dumps(data,clsCustomEncoder)反过来解码时需要自定义object_hook参数把字符串转回对象。但这容易引入歧义——怎么区分一个“2024-01-01”是日期还是普通字符串所以很多时候索性在业务逻辑里手动转换。4. 最佳实践实践中踩过的坑不少总结几条第一永远不要用eval代替json.loads。有人图省事用eval({a: 1})来解析这等于把攻击者请进门。比如恶意字符串exec(import os; os.rmdir(/))被eval执行后果严重。json.loads是安全的它只解析合法JSON不执行代码。第二大文件处理要流式读入。假如一个JSON文件有1GB一次json.load会吃掉大量内存。可以用ijson这样的流式解析库或者自己写逐行处理。如果JSON结构是每行一个对象JSON Lines格式可以用withopen(large.json,r)asf:forlineinf:objjson.loads(line)process(obj)注意这种文件每行必须是一个完整的JSON对象不能有换行符。第三格式化输出要谨慎。开发时用indent2方便调试但生产环境里输出给API的JSON应该紧凑节省带宽。先格式化再传输等于脱裤子放屁。同样sort_keysTrue在写测试时有用能让输出顺序固定方便对比。第四异常处理不能少。json.loads接收非法字符串会抛出json.JSONDecodeError不像eval悄无声息地执行恶意代码。要捕获异常告诉用户输入格式不对try:datajson.loads(user_input)exceptjson.JSONDecodeErrorase:print(f输入的JSON格式有误{e})第五JSON Schema验证是个好习惯。当别人给你传JSON数据时先用jsonschema库验证结构是否符合预期比如字段是否存在、类型对不对。虽然Python是动态语言但数据验证能避免很多运行时错误。5. 和同类技术对比JSON在数据序列化领域并不孤独。常见的对手有XML、YAML、Protocol Buffersprotobuf、MessagePack等。VS XMLXML像一把瑞士军刀功能强大但臃肿——有命名空间、属性、注释、嵌套结构。JSON则像一把小折刀轻巧够用。比如表示一个联系人XML写一堆标签JSON就几行键值对。性能上JSON解析更快因为语法更简单数据量更小。但XML有DTD/XSD做严格校验适合企业级文档交换。JSON的校验依赖第三方库标准库不提供。VS YAMLYAML主打人类可读性语法更简洁用缩进表示层级支持注释、引用、多行字符串。比如配置文件YAML比JSON更直观。但YAML的复杂度也是双刃剑——缩进错误会导致解析失败一些边缘情况比如时间格式、布尔值的true和yes容易踩坑。JSON则简单到几乎不会误解而且Python的json模块永远足够可靠。所以很多新项目比如Django的settings从YAML切回了JSON图的就是稳定。VS Protocol Buffersprotobuf是二进制格式为性能而生。它比JSON小得多因为不需要键名解析速度更快因为结构预定义。缺点是需要写.proto文件定义结构然后生成代码——学习成本高而且数据不是人可直接读的。JSON则天然可读适合调试。在微服务内部通信中protobuf有优势在前后端交互、开放API中JSON是事实标准。比如Google自己的Cloud API很多也公开JSON接口。VS MessagePackMessagePack是另一个二进制JSON替代品。它像JSON的压缩版本数据类型相似但体积更小、解析更快。Python的msgpack库用起来和json很相似。但它的生态不如JSON——主流语言都内置JSON支持而MessagePack需要额外安装。个人开发或小项目用JSON就够了对性能有极端要求比如游戏服务器MessagePack值得一试。总结下来JSON是“够用就好”的典范。它不完美——不支持二进制数据、没有注释、对大数字处理不友好Python的int会丢失精度、没有标准日期格式——但它的简单性让它赢得了市场。就像用筷子吃饭虽然不如刀叉优雅但胜在顺手。在Python生态里90%的场景下import json就能解决问题剩下的10%再考虑其他工具。