
简介该资源是面向Java开发者的JSON完整示例包聚焦JSON数据交换格式的语法学习与解析/生成实战。包体共22个文件、约2.88MB以json-lib系列jar包及commons等常用依赖为主同时包含可直接运行的Java源文件、编译后的class文件、项目配置文件以及一份JSON语法笔记导入IDE即可对照学习。目前已有3577人学习下载。示例覆盖JSON对象、数组、嵌套对象等基本结构演示字符串、数字、布尔值、null等数据类型的构建与读取并通过代码展示JSON与Java对象之间的相互转换。笔记部分还整理了键需双引号、末项不能带逗号等易错规则适合刚接触JSON、希望快速掌握数据交换技能的开发者参考也可直接移植到实际接口调试或Web开发中复用。1. 一个看似简单的格式为什么需要「完整例子」搜「json完整例子」的人通常不是没看过 JSON 教程而是手头正压着一批数据要么是接口文档只给了字段名没给结构要么是自己写的 JSON 被前端一句「解析失败」打回来要么是想把配置从 ini 迁到 JSON 却不知道怎么组织层级。JSON 的语法半小时能学完但「能写出来」和「一次写对」是两回事——完整例子的价值在于把字符串、数字、布尔、null、数组、对象六种数据类型按真实业务的形态组合起来让你看到嵌套、转义、空值这些写的时候必须做的决策。这篇文章给的是可以直接抄走的完整例子、真实场景模板和排错手段适合正在写接口、做配置、抓数据的开发者读完能少走很多弯路。2. JSON 语法基础从最小对象到完整数据类型示例2.1 六种数据类型完整例子首先要覆盖的对象JSON 的全部数据类型只有六种字符串、数字、布尔值、null、数组、对象。数量少但很多写错的人恰恰是在这六种类型的边界上栽的跟头。字符串必须用双引号包裹单引号不合法数字支持整数和小数但不能有前导零不能写 NaN 或 Infinity布尔值只有小写的 true 和 falsenull 表示空值但「字段缺失」和「值为 null」在解析结果里是两种完全不同的状态数组用方括号元素可以是任意类型也可以混合对象用花括号键必须是带双引号的字符串。我见过的常见误解是把 JSON 当成 JavaScript 对象字面量。两者写法高度相似但 JSON 是一套独立的数据交换格式它不允许注释、不允许尾逗号、不允许不加引号的键名。凡是「在 JS 里能跑」的写法放到 JSON.parse 里可能就是 SyntaxError。下面这张表把六种类型的合法写法和常见错误列在一起写之前扫一眼能省不少排错时间类型合法示例常见错误写法字符串name: 示例单引号、中文引号数字price: 19.90019、NaN、Infinity布尔active: trueTrue、False、1nullremark: nullnull、NULL数组tags: [a, b]用圆括号、元素缺逗号对象user: {id: 1}键不加引号、尾逗号2.2 一个覆盖全部语法的完整 JSON 示例文件下面这个例子故意把六种类型全部塞进去同时包含两层以上的嵌套你可以直接存成 example.json 做测试{ title: 订单数据示例, orderId: ORD-2024-001, amount: 2999.50, quantity: 3, inStock: true, urgent: false, remark: null, tags: [加急, 礼品, 已付款], customer: { name: 示例用户, level: 2, member: true, lastLoginAt: null }, items: [ { sku: SKU-A100, price: 899.00, attrs: { color: 黑, size: L } }, { sku: SKU-B200, price: 99.00, attrs: { color: 白, size: M } } ] }这个文件里title、orderId 是字符串amount、quantity、level 是数字inStock、urgent、member 是布尔值remark 和 lastLoginAt 是 nulltags 是字符串数组customer 是对象items 是对象数组attrs 是对象套对象。如果你想验证某个解析器的行为边界这个文件几乎覆盖了全部语法面。有几个点值得单独说。amount 写成 2999.50 是合法的但解析后会被当作 2999.5 处理小数末尾的 0 不会保留所以别指望 JSON 能保存「精确到分」的原始字符串金额这种字段要么用整数分存储要么用字符串。null 字段在序列化时通常会保留键名这和「直接不写这个键」不同后文会专门讲。缩进我这里用了两个空格是个人推荐的默认值紧凑、可读、深嵌套时不会让行宽失控。2.3 缩进、换行与格式化玄学还是规范缩进不影响 JSON 的合法性但影响排查问题的效率。两个空格和四个空格都常见团队内部统一即可真正影响合法性的只有三件事键必须带双引号、字符串必须用双引号、不允许尾逗号。缩进只是给人看的机器完全不关心。换行同理。JSON 里的空白字符在语法层面完全等价你可以把整个 JSON 压成一行做传输也可以格式化成一棵清晰的树。我一般遵循「传输用紧凑型、落盘用格式化」的习惯接口响应为了减小体积常常去空格本地配置文件则保持格式化方便 diff 和 review。如果你拿到一个被压缩成一行的大 JSON别用肉眼去读直接丢给格式化工具几秒钟就能变成可读结构。注意格式化工具只能调整空白和缩进不会帮你修复语法错误。如果 JSON 本身有尾逗号或单引号工具会直接报错这时候先按第 4 章的清单排查。3. 真实场景中的 JSON 完整例子配置文件与 API 响应3.1 把 JSON 当配置文件一个服务配置的完整例子JSON 做配置文件的优势是层级表达能力强ini 风格的扁平键值对在表达「数据库连接池 日志轮转 功能开关」这类组合时非常吃力。下面这个例子是一个典型的服务配置我把它当模板用了很久{ server: { host: 0.0.0.0, port: 8080, workers: 4, shutdownTimeoutSeconds: 30 }, database: { host: 127.0.0.1, port: 3306, name: app_db, user: app_user, password: change_me, poolSize: 10, options: { charset: utf8mb4, timezone: 08:00 } }, logging: { level: info, file: /var/log/app.log, maxSizeMb: 100, backupCount: 7 }, features: { enableCache: true, cacheTtlSeconds: 300, rateLimit: { enabled: true, maxRequestsPerMinute: 120 } } }层级设计是配置文件里最关键的决策。我的习惯是「第一层按模块分第二层按参数分超过两层就警惕」上面的 server、database、logging、features 是第一层options 和 rateLimit 是第二层嵌套再往下就建议拆成独立配置或用配置中心了。嵌套太深会让使用者每次取值都写一长串路径比如 features.rateLimit.maxRequestsPerMinute在代码里维护起来非常痛苦。这个配置里还藏着一个常用教训密码以明文写在 JSON 里。JSON 没有注释机制所以你不能像 ini 那样在文件里写「这是测试密码上线前要换」常见的做法是用环境变量占位符替代敏感字段或者在启动时由配置中心注入。至少要做到这个文件不进版本库。另外端口号写成数字而不是字符串是有意为之配置加载后会被类型化如果你的代码里 expects 字符串需要先做一次类型转换这是 YAML 和 JSON 配置里常见的类型陷阱。3.2 API 响应里的 JSON列表、分页与错误码怎么设计接口返回的 JSON 是另一个高频场景。下面是我推荐的一种「统一响应壳」结构所有接口都返回同一个外壳code 表示业务状态码message 是人类可读的说明data 放真正的业务数据{ code: 0, message: success, data: { list: [ { id: 1001, title: 第一个商品, price: 19.90, stock: 120, tags: [热销], seller: { id: 5, name: 店铺甲 } }, { id: 1002, title: 第二个商品, price: 299.00, stock: 0, tags: [], seller: { id: 9, name: 店铺乙 } } ], page: 1, pageSize: 10, total: 2 } }分页参数放在 data 里而不是外壳里是我见过比较稳妥的约定。code 为 0 表示成功非 0 表示业务失败HTTP 状态码只表达传输层结果比如 200、404、500业务成功与否由 code 决定两层分开前端才能精确处理「接口通了但业务失败」的情况。注意第二个商品的 stock 是 0而 tags 是空数组这两个值和 null 语义完全不同前端渲染时要区分「无库存」和「无标签」。一个容易踩的坑是错误响应格式不统一。有的接口失败时只返回{code: 500, message: error}有的直接把 data 丢掉还有的在 data 里塞一个 error 对象。我的建议是所有失败响应都保持和成功响应一样的外壳结构data 可以置 null但键不能缺。前端拿到响应先解外壳再解数据代码路径单一比到处判断某个键是否存在好维护得多。3.3 从接口返回里提取字段Python 与 JavaScript 的最小解析代码有了完整例子下一个诉求就是怎么解析。下面用 Python 和 JavaScript 各给一段最小解析代码。Python 侧用标准库 jsonimport json with open(api_response.json, r, encodingutf-8) as f: data json.load(f) if data[code] ! 0: raise RuntimeError(f业务错误: {data[message]}) page data[data][page] total data[data][total] print(f第 {page} 页共 {total} 条) for item in data[data][list]: title item[title] price item[price] stock item[stock] print(title, price, stock)这段代码先解析文件为 Python 字典再判断业务码最后遍历列表。参数说明json.load 接收文件对象json.loads 接收字符串两者别混文件必须用 encodingutf-8 打开否则含中文的 JSON 在部分环境下会抛 UnicodeDecodeError取嵌套字段要逐层用方括号比如 data[data][list]中间任何一层键不存在都会抛 KeyError不要指望缺键时返回 None。JavaScript 侧用内置的 JSON.parseconst data JSON.parse(responseText); if (data.code ! 0) { throw new Error(data.message); } const { list, page, total } data.data; console.log(第 ${page} 页共 ${total} 条); list.forEach((item) { console.log(item.title, item.price, item.stock); });JSON.parse 的入参必须是字符串如果你已经拿到一个对象再传给 JSON.parse 会原样返回不报错但也没有意义。解构赋值在这里很好用data.data.list 这种路径用解构一次拆平后续代码可读性会好很多。注意 responseText 的来源如果是 XMLHttpRequest要确认请求已完成且状态是 200否则 parse 的可能是空字符串直接抛 SyntaxError。4. 手写 JSON 的避坑指南5 个最常见的翻车现场4.1 尾逗号与单引号为什么编辑器不帮你纠错现象手写的 JSON 里最后一个键值对后面习惯性加了逗号或者所有字符串都用了单引号贴进代码里 JSON.parse 直接抛 SyntaxErrorPython 的 json.load 报 JSONDecodeError。原因JSON 规范明确禁止尾逗号也明确要求双引号。很多人在写 JavaScript 对象字面量时养成了加尾逗号、用单引号的习惯但 JSON 不是 JS 对象字面量解析器严格按规范执行不会因为你「看起来差不多」就放行。编辑器默认也不会把 .json 文件当 JS 处理语法高亮和自动纠错都不生效。解决写完后统一用工具校验。命令行里python -m json.tool data.json是最快的检查方式有语法错误会直接告诉你第几行第几个字符出问题编辑器里装带 JSON 校验的插件写错时实时标红。养成「写完即校验」的习惯后这类问题几乎不会再出现。4.2 数字与 null 的边界0、空字符串、缺失字段现象接口返回里字段值为 0、空字符串、null或者干脆没有这个键前端用 if(field) 判断时把它们全部当成 falsy导致「库存为 0 的商品」和「没有库存字段的商品」被当成同一种情况页面渲染错乱。原因JSON 里的空值语义和编程语言里的 falsy 语义不同。0 是有效数字空字符串是有效字符串null 是显式空值而字段缺失在解析结果里表现为「键不存在」。在 Python 里取缺失键会抛 KeyError在 JavaScript 里得到 undefined这两者都和 null 严格区分。解决前后端先约定语义。我一般规定有值就写真实值无值用 null绝不通过「不写这个键」来表达空。前端判断时用value null同时覆盖 null 和 undefined再用value 0、value 精确处理边界。不要用 if(value) 这种宽松判断处理业务字段它会把 0 和空字符串一起吞掉。4.3 转义字符与 Unicode中文变成 \uXXXX 怎么办现象从接口拿到的 JSON 里中文全是 \u4f60\u597d 这样的转义序列看着像乱码或者字符串里本身包含双引号和反斜杠手写时没转义解析直接报错。原因JSON 字符串里的双引号必须写成 反斜杠必须写成 \这是语法要求。而中文变成 \uXXXX 通常是发送方在序列化时开启了 ASCII 转义比如 Python 的 json.dumps 默认会把非 ASCII 字符转成 \u 序列这是合法 JSON只是人眼不友好。解决不要手改转义序列。解析后正常显示中文格式化工具也会还原 Unicode如果你要自己生成 JSON用语言自带的序列化函数而不是字符串拼接。Python 里 json.dumps(data, ensure_asciiFalse) 可以保留中文配合 indent 参数控制缩进生成的文件直接可读。记住一个原则JSON 的读写都应该经过解析器永远不要手工拼接字符串。4.4 嵌套层级过深解析器真的会拒绝吗现象一个 JSON 嵌套了 50 层Python 的 json.load 抛 RecursionError某些 C 语言实现的解析器直接栈溢出进程崩溃。原因递归下降解析器按调用栈处理嵌套默认递归深度有限制。Python 的 json 模块在嵌套超过约 1000 层时会触发 RecursionErrorC 系解析器可能更早出问题。深度嵌套的数据大多数来自程序自动生成手写很少会触发但一旦触发就是进程级故障比语法错误严重得多。解决设计数据结构时把嵌套控制在 10 层以内这既是解析安全也是可读性要求。超过 10 层应该考虑用展开的列表加 id 引用来建模比如把无限级菜单改成平铺节点数组加 parentId 字段。如果数据源是别人给的、无法控制深度改用流式解析器Python 里可以换用 ijson它边读边解析不依赖调用栈深度。4.5 用工具验证json.tool 与在线校验器的取舍现象肉眼审查了几遍觉得没问题发给对方还是被退回最后发现是某个字符串里的双引号没转义。这种事非常常见尤其是嵌套多、字符串长的 JSON人脑会自动忽略结构错误。原因肉眼检查对嵌套多、字符串长的 JSON 不可靠引号配对这种需要逐字符确认的细节人眼很容易跳过。写完 JSON 直接复制粘贴到业务代码里等运行时报错再回头查中间的时间全部浪费了。解决本地命令行工具是首选。python -m json.tool data.json能校验并格式化jq . data.json同样能做额外还能提取字段、过滤数据。在线校验器只在万不得已时用把接口数据贴到网页上有泄露风险尤其是包含用户信息或内部字段的数据。我现在的习惯是任何手动改过的 JSON提交前必须过一遍 json.tool这个动作十秒钟能挡掉绝大多数低级错误属于投入产出比最高的一道防线。5. JSON Schema给「完整例子」加一道质量检验5.1 为什么光有例子不够完整例子能告诉你数据「长什么样」但不能保证别人写的或程序生成的数据「符合预期」。对方可能漏了必填字段可能把 price 传成了字符串可能嵌套结构完全不对。这个时候需要 JSON Schema——用一份描述性文件规定数据结构数据进来先校验不合格直接拒收不用等运行到业务逻辑深处才爆出诡异问题。JSON Schema 本身也是一个 JSON这是它最妙的地方定义结构的文件和被校验的数据用同一种格式表达。它支持声明必填字段、字段类型、取值范围、数组长度、对象嵌套规则是给「完整例子」加自动化检验最直接的手段。把 Schema 挂在接口文档旁边等于把「例子」升级成了「契约」。5.2 一个最小可用的 Schema 示例对应第 2.2 节的订单例子写一个最小 Schema校验它的核心字段{ $schema: http://json-schema.org/draft-07/schema#, title: 订单数据校验, type: object, required: [orderId, amount, customer, items], properties: { orderId: { type: string, minLength: 1 }, amount: { type: number, minimum: 0 }, inStock: { type: boolean }, remark: { type: [string, null] }, tags: { type: array, items: { type: string }, maxItems: 20 }, customer: { type: object, required: [name], properties: { name: { type: string }, level: { type: integer, minimum: 1, maximum: 5 } } }, items: { type: array, minItems: 1, items: { type: object, required: [sku, price], properties: { sku: { type: string }, price: { type: number, minimum: 0 } } } } } }这段 Schema 里最值得注意的声明required 数组列出必须存在的键remark 的 type 是[string, null]表示它允许为空amount 用 minimum 限制不能为负items 里的元素对象被递归声明了结构数组内每个对象都必须有 sku 和 price。每一层嵌套都要写对应的 type 和 properties这正是「完整例子」变成「完整契约」的过程例子给的是形态Schema 给的是约束。注意一个细节level: { type: integer }卡住了浮点数如果你接口里的 level 可能返回 2.5这里会校验失败所以定义 Schema 前要先确认业务上真的只接受整数。Schema 写得越严误伤越多写得越松校验越没意义。这个度需要对着真实数据调几轮。5.3 用 Schema 校验数据的命令行实践Python 生态里有现成的 jsonschema 库安装后几行代码就能跑校验pip install jsonschema校验脚本import json from jsonschema import validate, ValidationError with open(schema.json, r, encodingutf-8) as f: schema json.load(f) with open(data.json, r, encodingutf-8) as f: data json.load(f) try: validate(instancedata, schemaschema) print(校验通过) except ValidationError as e: print(f校验失败: {e.message}) print(f出错位置: {list(e.path)})validate 函数接收两个参数instance 是要校验的数据schema 是结构定义。校验失败时 ValidationError 会带出具体错误信息和字段路径比如19.9 is not of type integer一眼就能定位问题。如果你不想写脚本也可以用命令行工具 check-jsonschema把 schema 文件和待校验文件直接丢给它。我一般在接口联调阶段就把 Schema 挂进自动化测试每次 mock 数据先过 Schema再进业务代码。这样「例子对不对」由机器说了算而不是靠人肉 review。Schema 和例子放同一个目录改接口先改 Schema 再改例子两边漂移会大幅减少。这也是一个能被团队长期复用的资产比散落在文档里的字段说明可靠得多。6. 把 JSON 例子变成自己的模板格式化与生成技巧先记一个通用习惯拿到任何 JSON 第一件事是jq .格式化而不是直接打开看。压缩成一行的大 JSON 用肉眼读是灾难格式化后结构一目了然。jq 还能顺手提取字段比如从第 3.2 节的接口响应里只挑商品名和价格jq . data.json jq .data.list[] | {title, price} api_response.json第一个命令做格式化校验第二个命令做字段提取。jq 的过滤器语法值得花半小时学它是处理 JSON 最顺手的命令行工具比 grep 可靠得多。第二个习惯JSON 靠代码生成不靠手写。尤其是配置文件和接口响应这种会被反复修改的结构手写容易漏引号、加错逗号生成则永远正确。下面是一段 Python 生成配置文件的脚本import json config { server: { host: 0.0.0.0, port: 8080, workers: 4 }, features: { enableCache: True, cacheTtlSeconds: 300 } } with open(config.json, w, encodingutf-8) as f: json.dump(config, f, ensure_asciiFalse, indent2)json.dump 的三个关键参数ensure_asciiFalse 保留中文原文indent2 输出带缩进的格式化文本sort_keysTrue 可选按字母序排键方便 diff。生成完毕后仍然跑一遍 json.tool 确认双保险。第三个习惯是维护自己的模板库。把第 2.2 节的完整类型示例、第 3.1 节的配置模板、第 3.2 节的接口响应壳、第 5.2 节的 Schema 骨架存成模板文件新建项目直接复制改字段比每次从零开始写省很多时间。我吃过一次亏某个项目里手写了一个 200 行的嵌套 JSON没校验就提交结果 CI 直接挂掉排查发现是第三层某个字符串忘了转义那之后所有 JSON 改动都必须过工具不再相信自己的眼睛。希望你从第一个 JSON 起就养成这个习惯少走我走过的弯路希望帮到你。本文还有配套的精品资源点击获取