JSON

返回 计算机网络

JSON(JavaScript Object Notation)是一种轻量级的文本数据交换格式,语法源于 JavaScript 对象字面量,因可读性好、语言无关,成为前后端交互和配置文件的事实标准。


数据类型

类型示例
字符串"hello"
数字423.14-1
布尔值truefalse
空值null
数组[1, "two", true]
对象{"key": "value"}

语法规则

{
  "name": "Alice",
  "age": 30,
  "isAdmin": false,
  "tags": ["java", "spring"],
  "address": {
    "city": "Beijing",
    "zip": "100000"
  },
  "avatar": null
}
  • 键名必须用双引号包裹
  • 字符串值用双引号,不可用单引号
  • 末尾不允许有多余逗号(trailing comma)
  • 不支持注释

常用操作

JavaScript

// 序列化:对象 → JSON 字符串
const json = JSON.stringify({ name: 'Alice', age: 30 })
 
// 格式化输出
const pretty = JSON.stringify(obj, null, 2)
 
// 反序列化:JSON 字符串 → 对象
const obj = JSON.parse('{"name":"Alice","age":30}')
 
// 深拷贝(简单场景)
const copy = JSON.parse(JSON.stringify(original))

Java(Jackson)

ObjectMapper mapper = new ObjectMapper();
 
// 序列化
String json = mapper.writeValueAsString(user);
 
// 反序列化
User user = mapper.readValue(json, User.class);
 
// 忽略未知字段
@JsonIgnoreProperties(ignoreUnknown = true)
public class User { ... }

Python

import json
 
# 序列化
json_str = json.dumps({"name": "Alice", "age": 30}, ensure_ascii=False)
 
# 反序列化
obj = json.loads(json_str)
 
# 读写文件
with open("data.json", "w") as f:
    json.dump(data, f, ensure_ascii=False, indent=2)

JSON vs 其他格式

格式优点缺点适用场景
JSON可读性好,语言支持广体积偏大,无注释REST API,配置文件
XML结构严谨,支持 schema冗余标签,解析慢传统 SOAP,文档型数据
YAML可读性最好,支持注释缩进敏感,解析复杂配置文件(Docker、K8s)
Protobuf体积小,解析快二进制不可读,需 schemagRPC,高性能微服务

常见语言操作补充

Go

import "encoding/json"
 
type User struct {
    Name  string `json:"name"`
    Age   int    `json:"age"`
    Email string `json:"email,omitempty"` // 空值时省略
}
 
// 序列化
data, err := json.Marshal(User{Name: "Alice", Age: 30})
 
// 格式化
data, err := json.MarshalIndent(user, "", "  ")
 
// 反序列化
var u User
err = json.Unmarshal([]byte(jsonStr), &u)
 
// 流式解码(大文件)
decoder := json.NewDecoder(r)
decoder.Decode(&u)

TypeScript

// 类型安全的反序列化(运行时无校验,需手动断言或用 zod)
interface User { name: string; age: number }
const user = JSON.parse(jsonStr) as User
 
// 使用 zod 进行运行时校验
import { z } from 'zod'
const UserSchema = z.object({ name: z.string(), age: z.number() })
const user = UserSchema.parse(JSON.parse(jsonStr))  // 类型错误时抛出

JSON Schema

用 JSON 描述 JSON 结构,用于校验数据合法性:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "name": { "type": "string", "minLength": 1 },
    "age":  { "type": "integer", "minimum": 0, "maximum": 150 }
  },
  "required": ["name", "age"]
}

常用工具:ajv(Node.js)、jsonschema(Python)、Jackson 的 @Valid 集成。


NDJSON / JSON Lines

每行一个独立 JSON 对象,适合流式处理和日志:

{"id":1,"event":"login","user":"alice"}
{"id":2,"event":"purchase","amount":99.9}
{"id":3,"event":"logout","user":"alice"}

优势:逐行读取无需加载全部数据到内存,适合日志收集(Logstash、Kafka)。


注意事项

  • 数字精度:超过 53 位整数(Java Long)传给 JS 会丢失精度,应转为字符串
  • 日期:JSON 无原生日期类型,通常用 ISO 8601 字符串("2024-01-01T00:00:00Z")或时间戳(毫秒数)
  • null vs 缺失字段"field": null 与不包含该字段语义不同,序列化时需注意
  • 循环引用JSON.stringify 遇到循环引用会抛出,需先处理或使用 replacer
  • 特殊浮点数NaNInfinity-Infinity 在 JSON 中无效,序列化结果为 null

安全注意事项

问题说明防护
Prototype 污染{"__proto__": {"isAdmin": true}} 篡改原型链使用 Object.create(null) 或安全解析库
JSON 注入用户输入直接拼接进 JSON 字符串始终使用序列化库,不手动拼接
敏感字段泄露序列化时包含密码、Token 等字段使用 @JsonIgnore / omitempty 排除敏感字段
超大 JSON 解析恶意超大 JSON 耗尽内存设置最大 Body 大小,使用流式解析

相关

  • 前后端交互 — JSON 是前后端数据交换的默认格式
  • HTTP — JSON 通常作为 HTTP 请求/响应体
  • 网络通信 — JSON 是最常用的网络数据序列化格式
  • 通信协议 — 与 Protobuf、XML 等其他序列化协议对比
  • 网络安全 — JSON 相关安全风险