Python 加载 JSON 字符串后是什么类型?新手一篇搞懂
Python 加载 JSON 字符串后是什么类型?新手一篇搞懂
很多 Python 新手刚接触 JSON 时,都会有一个疑问:
我用
json.loads()加载 JSON 字符串以后,得到的到底是什么?
答案不是固定的。它可能是字典,也可能是列表,也可能只是一个字符串、数字、布尔值,甚至是 None。
这篇文章就用大白话讲清楚:不同 JSON 字符串结构加载到 Python 后,对应什么数据类型,以及拿到这些类型后该怎么用。
本文所有代码都可以直接复制运行。
一、基础入门:先搞懂核心前提
1. 什么是 JSON 字符串
JSON 可以先简单理解成一种“用字符串保存数据的格式”。
比如下面这个就是 JSON 字符串:
'{"name": "张三", "age": 18}'
注意,它外面是一整段字符串,里面看起来像 Python 字典,但它本质上还是字符串。
我们可以用代码验证一下:
# 这是一段 JSON 字符串
json_str = '{"name": "张三", "age": 18}'
# 打印内容
print(json_str)
# 查看类型
print(type(json_str)) # <class 'str'>
输出里会看到:它在 Python 里一开始是 str 类型,也就是字符串。
那怎么把这段字符串变成 Python 能直接使用的数据呢?这就要用到 json 模块。
2. Python 加载 JSON 字符串的工具:json.loads()
Python 内置了 json 模块,不需要单独安装。
我们最常用的是:
json.loads(JSON字符串)
loads() 可以把 JSON 字符串“加载”为 Python 数据。
import json
# JSON 字符串
json_str = '{"name": "张三", "age": 18}'
# 使用 json.loads() 加载
data = json.loads(json_str)
print(data) # {'name': '张三', 'age': 18}
print(type(data)) # <class 'dict'>
这里加载后得到的是 dict,也就是 Python 字典。
3. 核心结论:加载后类型取决于 JSON 顶层结构
新手一定要记住这个结论:
JSON 字符串加载后,不会永远变成字典。它会根据 JSON 最外层的结构,变成对应的 Python 类型。
可以这样理解:
- JSON 字符串像一个包装盒。
- 最外层的结构,就是盒子的形状。
- Python 加载后得到的类型,就是拆开盒子后里面的东西。
常见对应关系如下:
| JSON 顶层结构 | JSON 示例 | Python 加载后类型 |
|---|---|---|
对象 {} |
{"name": "小白"} |
字典 dict |
数组 [] |
[1, 2, 3] |
列表 list |
| 字符串 | "Python" |
字符串 str |
| 整数 | 123 |
整数 int |
| 小数 | 3.14 |
浮点数 float |
| 布尔值 | true / false |
布尔值 True / False |
| 空值 | null |
None |
先用一段代码整体感受一下:
import json
examples = [
'{"name": "小白"}', # JSON 对象
'[1, 2, 3]', # JSON 数组
'"Python"', # JSON 字符串
'123', # JSON 整数
'3.14', # JSON 小数
'true', # JSON 布尔值
'null' # JSON 空值
]
for json_str in examples:
data = json.loads(json_str)
print(json_str, "=>", data, "=>", type(data))
二、核心重点:不同 JSON 结构对应 Python 类型
1. JSON 顶层是对象 {}:对应 Python 字典 dict
JSON 对象就是用 {} 包起来的数据,里面是一组一组的“名字和值”。
比如:
{"name": "小白", "learn": "Python"}
加载后对应 Python 的 dict,也就是字典。
demo1:简单 JSON 对象字符串加载
import json
# JSON 顶层是对象,用 {} 包裹
json_str = '{"name": "小白", "learn": "Python"}'
# 加载 JSON 字符串
data = json.loads(json_str)
# 打印加载后的内容
print(data)
# 验证类型:JSON 对象 -> Python 字典
print(type(data)) # <class 'dict'>
# 字典可以通过键访问值
print(data["name"]) # 小白
print(data["learn"]) # Python
这里最外层是 {},所以加载后是字典。
字典的用法很直观:想拿哪个值,就用对应的键。
print(data["name"])
意思就是:从字典里拿出 name 对应的值。
demo2:实际场景:加载配置信息
项目里经常会把配置写成 JSON,比如数据库地址、端口、调试开关等。
import json
# 模拟一段配置 JSON 字符串
config_json = '''
{
"host": "127.0.0.1",
"port": 3306,
"debug": true
}
'''
# 加载后得到字典
config = json.loads(config_json)
print("加载后的类型:", type(config)) # <class 'dict'>
# 根据键访问配置
print("数据库地址:", config["host"])
print("数据库端口:", config["port"])
print("是否开启调试:", config["debug"])
# 修改配置:把 debug 改成 False
config["debug"] = False
print("修改后的配置:", config)
这类 JSON 很适合加载成字典,因为字典本来就适合保存“配置名 -> 配置值”。
2. JSON 顶层是数组 []:对应 Python 列表 list
JSON 数组就是用 [] 包起来的一组数据。
比如:
[{"name": "小白"}, {"name": "小黑"}]
加载后对应 Python 的 list,也就是列表。
demo1:简单数组 JSON 字符串加载
import json
# JSON 顶层是数组,用 [] 包裹
json_str = '[{"name": "小白"}, {"name": "小黑"}]'
# 加载 JSON 字符串
data = json.loads(json_str)
print(data)
# 验证类型:JSON 数组 -> Python 列表
print(type(data)) # <class 'list'>
# 列表可以通过索引访问元素
print(data[0]) # {'name': '小白'}
print(data[1]) # {'name': '小黑'}
这里最外层是 [],所以加载后是列表。
列表里的每个元素又是一个字典,所以可以继续通过键访问:
import json
json_str = '[{"name": "小白"}, {"name": "小黑"}]'
data = json.loads(json_str)
# 第一步:data[0] 拿到第一个字典
# 第二步:["name"] 从字典里拿 name
print(data[0]["name"]) # 小白
demo2:实际场景:加载多个用户信息
接口经常会返回多条用户数据,这种结构通常就是 JSON 数组。
import json
users_json = '''
[
{"id": 1, "name": "小白", "vip": true},
{"id": 2, "name": "小黑", "vip": false},
{"id": 3, "name": "小蓝", "vip": true}
]
'''
# 加载后得到列表
users = json.loads(users_json)
print("加载后的类型:", type(users)) # <class 'list'>
# 遍历列表,每次拿到一个用户字典
for user in users:
print("用户ID:", user["id"])
print("用户名:", user["name"])
print("是否会员:", user["vip"])
print("-" * 20)
# 访问第一个用户
first_user = users[0]
print("第一个用户:", first_user)
print("第一个用户的名字:", first_user["name"])
新手记住一句话:
最外层是
[],先按列表处理;列表里的元素如果是{},再按字典处理。
3. JSON 顶层是单一值:对应 Python 基础类型
JSON 的最外层不一定非得是 {} 或 []。
它也可以只是一个单独的字符串、数字、布尔值或 null。
3.1 JSON 字符串:对应 Python str
注意:JSON 字符串里面必须用双引号。
import json
# JSON 字符串值,外层 Python 字符串用单引号,里面 JSON 值用双引号
json_str = '"Python"'
data = json.loads(json_str)
print(data) # Python
print(type(data)) # <class 'str'>
# 加载后就是普通 Python 字符串,可以使用字符串方法
print(data.upper()) # PYTHON
实际场景:加载单个配置值。
import json
# 比如某个配置项只保存数据库名
db_name_json = '"test_database"'
db_name = json.loads(db_name_json)
print("数据库名:", db_name)
print("数据库名长度:", len(db_name))
3.2 JSON 整数:对应 Python int
import json
json_str = '123'
data = json.loads(json_str)
print(data) # 123
print(type(data)) # <class 'int'>
# 加载后可以直接做数字运算
print(data + 10) # 133
实际场景:加载端口号。
import json
port_json = '8080'
port = json.loads(port_json)
print("端口号:", port)
print("下一个端口:", port + 1)
3.3 JSON 小数:对应 Python float
import json
json_str = '3.14'
data = json.loads(json_str)
print(data) # 3.14
print(type(data)) # <class 'float'>
# 加载后可以参与小数运算
print(data * 2) # 6.28
实际场景:加载折扣。
import json
discount_json = '0.8'
discount = json.loads(discount_json)
price = 100
final_price = price * discount
print("原价:", price)
print("折后价:", final_price)
3.4 JSON 布尔值:对应 Python bool
JSON 里布尔值是小写的 true 和 false。
Python 里布尔值是首字母大写的 True 和 False。
json.loads() 会自动帮我们转换。
import json
json_str = 'true'
data = json.loads(json_str)
print(data) # True
print(type(data)) # <class 'bool'>
if data:
print("当前开关是打开状态")
实际场景:加载功能开关。
import json
debug_json = 'false'
debug = json.loads(debug_json)
if debug:
print("调试模式已开启")
else:
print("调试模式已关闭")
3.5 JSON null:对应 Python None
JSON 里的 null 表示“没有值”。
加载到 Python 后对应 None。
import json
json_str = 'null'
data = json.loads(json_str)
print(data) # None
print(type(data)) # <class 'NoneType'>
if data is None:
print("当前没有值")
实际场景:用户暂时没有填写手机号。
import json
phone_json = 'null'
phone = json.loads(phone_json)
if phone is None:
print("用户还没有填写手机号")
else:
print("用户手机号:", phone)
三、用法延伸:加载 JSON 后该怎么用
理解类型只是第一步,更重要的是知道拿到不同类型后应该怎么操作。
1. 字典类型:适合配置、单条数据
JSON 对象加载后是字典,常见场景有:
- 配置信息
- 接口返回的一条用户数据
- 一条商品信息
示例:加载配置 JSON,获取数据库地址。
import json
config_json = '''
{
"database": {
"host": "127.0.0.1",
"port": 3306,
"name": "shop"
},
"debug": true
}
'''
config = json.loads(config_json)
# config 是字典
print(type(config)) # <class 'dict'>
# database 对应的值也是一个字典
database = config["database"]
print(type(database)) # <class 'dict'>
# 继续通过键访问
print("数据库地址:", database["host"])
print("数据库端口:", database["port"])
# 修改配置
config["debug"] = False
print("修改后的 debug:", config["debug"])
可以直接写成一行访问嵌套值:
import json
config_json = '{"database": {"host": "127.0.0.1", "port": 3306}}'
config = json.loads(config_json)
# 一层一层通过键访问
host = config["database"]["host"]
print(host)
2. 列表类型:适合多条数据
JSON 数组加载后是列表,常见场景有:
- 多个用户
- 多个商品
- 多条订单
- 多条日志
示例:遍历所有用户,提取用户名。
import json
users_json = '''
[
{"id": 1, "name": "小白", "age": 18},
{"id": 2, "name": "小黑", "age": 20},
{"id": 3, "name": "小蓝", "age": 19}
]
'''
users = json.loads(users_json)
# users 是列表
print(type(users)) # <class 'list'>
# 遍历列表
for user in users:
# user 是列表中的一个元素,这里每个 user 都是字典
print(user["name"])
修改列表中的某个元素:
import json
users_json = '''
[
{"id": 1, "name": "小白", "age": 18},
{"id": 2, "name": "小黑", "age": 20}
]
'''
users = json.loads(users_json)
# 修改第一个用户的年龄
users[0]["age"] = 19
print(users)
3. 单一值类型:适合单个配置项
如果 JSON 字符串只是一个单独的值,加载后就按对应的 Python 类型使用。
比如单独加载一个端口号:
import json
port_json = '8080'
port = json.loads(port_json)
print(type(port)) # <class 'int'>
print("服务启动端口:", port)
也可以从 JSON 对象里提取单个值:
import json
config_json = '{"port": 8080, "db_name": "test"}'
config = json.loads(config_json)
port = config["port"]
db_name = config["db_name"]
print(type(port)) # <class 'int'>
print(type(db_name)) # <class 'str'>
print("端口:", port)
print("数据库名:", db_name)
特别提醒:
'"db_name": "test"'
这不是合法的 JSON。因为键值对必须放在 {} 里面。
正确写法:
import json
# 键值对必须放在 {} 中
json_str = '{"db_name": "test"}'
data = json.loads(json_str)
print(data["db_name"])
如果只想表示一个字符串值,应该写成:
import json
# 单一字符串值
json_str = '"test"'
data = json.loads(json_str)
print(data)
四、避坑指南:新手最容易踩的坑
坑 1:把 JSON 数组当作字典访问
错误原因:最外层是 [],加载后是列表,但你却用字典的键去访问。
错误 demo:
import json
json_str = '[{"name": "小白"}, {"name": "小黑"}]'
data = json.loads(json_str)
try:
# data 是列表,不是字典,不能直接 data["name"]
print(data["name"])
except TypeError as e:
print("出错了:", e)
正确 demo:先看类型,再按列表方式使用。
import json
json_str = '[{"name": "小白"}, {"name": "小黑"}]'
data = json.loads(json_str)
print(type(data)) # <class 'list'>
# 先用索引拿到第一个元素
first_user = data[0]
# first_user 是字典,再用键访问
print(first_user["name"])
更稳妥的写法:先判断类型。
import json
json_str = '[{"name": "小白"}, {"name": "小黑"}]'
data = json.loads(json_str)
if isinstance(data, list):
for user in data:
print(user["name"])
elif isinstance(data, dict):
print(data["name"])
else:
print("当前数据既不是列表,也不是字典")
坑 2:JSON 字符串格式错误
JSON 格式比 Python 字典更严格。
常见错误:
- 字符串必须用双引号,不能用单引号。
- 键和值之间用冒号。
- 多个键值对之间要有逗号。
- 最后一个键值对后面不能多写逗号。
错误 demo:键没有使用双引号。
import json
# 错误:name 没有双引号
bad_json = '{name: "小白", "age": 18}'
try:
data = json.loads(bad_json)
except json.JSONDecodeError as e:
print("JSON 格式错误:", e)
正确 demo:
import json
# 正确:键和值中的字符串都使用双引号
good_json = '{"name": "小白", "age": 18}'
data = json.loads(good_json)
print(data)
错误 demo:缺少逗号。
import json
# 错误:"小白" 和 "age" 中间缺少逗号
bad_json = '{"name": "小白" "age": 18}'
try:
data = json.loads(bad_json)
except json.JSONDecodeError as e:
print("JSON 格式错误:", e)
正确 demo:
import json
good_json = '{"name": "小白", "age": 18}'
data = json.loads(good_json)
print(data)
坑 3:把 None 当作字符串使用
JSON 里的 null 加载到 Python 后是 None,不是字符串 "null"。
错误 demo:
import json
json_str = '{"phone": null}'
data = json.loads(json_str)
phone = data["phone"]
try:
# phone 是 None,不能调用字符串方法
print(phone.strip())
except AttributeError as e:
print("出错了:", e)
正确 demo:使用前先判断是不是 None。
import json
json_str = '{"phone": null}'
data = json.loads(json_str)
phone = data["phone"]
if phone is None:
print("手机号为空")
else:
print(phone.strip())
如果你希望空值变成默认文案,也可以这样写:
import json
json_str = '{"phone": null}'
data = json.loads(json_str)
phone = data["phone"]
# 如果 phone 是 None,就使用默认值
phone_text = phone if phone is not None else "未填写"
print(phone_text)
坑 4:加载 JSON 对象后,用索引访问
JSON 对象加载后是字典,字典不能用位置索引访问。
错误 demo:
import json
json_str = '{"name": "小白", "age": 18}'
data = json.loads(json_str)
try:
# data 是字典,不是列表
print(data[0])
except KeyError as e:
print("出错了:字典中没有这个键:", e)
正确 demo:通过键访问。
import json
json_str = '{"name": "小白", "age": 18}'
data = json.loads(json_str)
print(data["name"])
print(data["age"])
如果想遍历字典内容,用 items():
import json
json_str = '{"name": "小白", "age": 18}'
data = json.loads(json_str)
for key, value in data.items():
print(key, "=>", value)
坑 5:中文显示乱码
json.loads() 加载中文字符串通常不会乱码。很多乱码问题发生在“保存 JSON 文件”或“把 Python 数据转回 JSON 字符串”时。
先看 loads() 正常加载中文:
import json
json_str = '{"name": "张三", "city": "北京"}'
data = json.loads(json_str)
print(data["name"])
print(data["city"])
如果你要把 Python 数据转成 JSON 字符串,默认可能会把中文变成 \uXXXX 形式。
虽然这不是错误,但新手看起来会觉得像乱码。
import json
data = {
"name": "张三",
"city": "北京"
}
# 默认 ensure_ascii=True,中文会被转义
json_str = json.dumps(data)
print(json_str)
正确 demo:使用 ensure_ascii=False 保留中文。
import json
data = {
"name": "张三",
"city": "北京"
}
# ensure_ascii=False 表示不要把中文转成 \uXXXX
json_str = json.dumps(data, ensure_ascii=False)
print(json_str)
如果是读取 JSON 文件,建议明确指定编码:
import json
# 假设 config.json 是 UTF-8 编码保存的文件
with open("config.json", "r", encoding="utf-8") as f:
data = json.load(f)
print(data)
这里用的是 json.load(f),它用于读取文件对象;而 json.loads(json_str) 用于读取 JSON 字符串。
一个字母的区别:
loads():加载字符串。load():加载文件。
五、实战案例:加载 JSON 字符串实现简单配置管理
这个案例会串联前面的知识点:
- 加载一个配置 JSON 字符串。
- 配置中同时包含对象、数组、字符串、数字、布尔值、null。
- 验证加载后的 Python 类型。
- 读取配置。
- 修改配置。
- 处理 JSON 格式错误。
- 演示中文输出不乱码。
案例完整代码
import json
def load_config(json_str):
"""
加载配置 JSON 字符串。
如果 JSON 格式错误,返回 None。
"""
try:
config = json.loads(json_str)
return config
except json.JSONDecodeError as e:
print("配置加载失败,JSON 格式有问题:", e)
return None
def show_type_info(config):
"""展示配置中不同字段对应的 Python 类型"""
print("整个配置的类型:", type(config))
print("app_name 的类型:", type(config["app_name"]))
print("version 的类型:", type(config["version"]))
print("debug 的类型:", type(config["debug"]))
print("database 的类型:", type(config["database"]))
print("users 的类型:", type(config["users"]))
print("description 的类型:", type(config["description"]))
def read_config(config):
"""读取配置内容"""
print("\n读取配置:")
# 读取普通字符串
print("项目名称:", config["app_name"])
# 读取数字
print("版本号:", config["version"])
# 读取布尔值
if config["debug"]:
print("当前是调试模式")
else:
print("当前是正式模式")
# 读取嵌套字典
database = config["database"]
print("数据库地址:", database["host"])
print("数据库端口:", database["port"])
# 读取列表
print("用户列表:")
for user in config["users"]:
print("-", user["name"], "角色:", user["role"])
# 读取 None
if config["description"] is None:
print("项目描述:暂无")
else:
print("项目描述:", config["description"])
def update_config(config):
"""修改配置内容"""
print("\n修改配置:")
# 修改普通字段
config["debug"] = False
# 修改嵌套字典中的字段
config["database"]["host"] = "192.168.1.100"
# 修改列表中第一个用户的信息
config["users"][0]["role"] = "super_admin"
print("debug 修改为:", config["debug"])
print("数据库地址修改为:", config["database"]["host"])
print("第一个用户角色修改为:", config["users"][0]["role"])
def export_config(config):
"""把 Python 配置数据重新转成 JSON 字符串"""
print("\n导出配置:")
# ensure_ascii=False 可以让中文正常显示
# indent=4 可以让 JSON 字符串更好看
json_text = json.dumps(config, ensure_ascii=False, indent=4)
print(json_text)
# 这是一段完整的配置 JSON 字符串
config_json = '''
{
"app_name": "新手配置系统",
"version": 1,
"debug": true,
"database": {
"host": "127.0.0.1",
"port": 3306
},
"users": [
{"name": "小白", "role": "admin"},
{"name": "小黑", "role": "user"}
],
"description": null
}
'''
# 第一步:加载 JSON 字符串
config = load_config(config_json)
# 第二步:确认加载成功后再继续使用
if config is not None:
show_type_info(config)
read_config(config)
update_config(config)
export_config(config)
# 再演示一个格式错误的 JSON
bad_json = '{"name": "小白" "age": 18}'
print("\n尝试加载错误 JSON:")
bad_config = load_config(bad_json)
if bad_config is None:
print("错误 JSON 没有继续处理,程序没有崩溃")
实现思路讲解
这段代码最重要的是三点:
第一,先用 json.loads() 把 JSON 字符串变成 Python 数据。
config = json.loads(json_str)
第二,加载后先看类型,再决定怎么用。
print(type(config))
如果是字典,就用键访问:
config["app_name"]
如果是列表,就用索引或循环:
config["users"][0]
for user in config["users"]:
print(user)
第三,处理错误,避免 JSON 格式错误时程序直接崩溃。
try:
config = json.loads(json_str)
except json.JSONDecodeError:
print("JSON 格式错误")
这就是实际项目里非常常见的写法。
六、补充:JSON 文件怎么加载
前面重点讲的是 JSON 字符串,因为你需要理解 json.loads() 加载后是什么类型。
实际项目中,我们也经常从 .json 文件读取配置。
假设有一个 config.json 文件,内容如下:
{
"app_name": "文件配置系统",
"port": 8080,
"debug": true
}
读取方式:
import json
# 从 JSON 文件中读取数据
with open("config.json", "r", encoding="utf-8") as f:
config = json.load(f)
print(config)
print(type(config)) # <class 'dict'>
print(config["app_name"])
print(config["port"])
注意:
json.loads():用于 JSON 字符串。json.load():用于 JSON 文件。
再看一个读取 JSON 数组文件的例子。
假设 users.json 内容如下:
[
{"name": "小白", "age": 18},
{"name": "小黑", "age": 20}
]
读取代码:
import json
with open("users.json", "r", encoding="utf-8") as f:
users = json.load(f)
print(type(users)) # <class 'list'>
for user in users:
print(user["name"], user["age"])
文件里的顶层结构仍然决定加载后的 Python 类型:
- 文件最外层是
{},加载后是字典。 - 文件最外层是
[],加载后是列表。
总结
新手学习 JSON 加载时,最核心的不是死记代码,而是记住这条规则:
JSON 最外层是什么结构,
json.loads()加载后就对应什么 Python 类型。
重点对应关系再记一遍:
{}->dict[]->list"文本"->str123->int3.14->floattrue/false->boolnull->None
实际使用时,先判断类型,再用对应方式操作:
- 字典用键访问:
data["name"] - 列表用索引或循环:
data[0]、for item in data - 字符串用字符串方法:
strip()、upper() - 数字可以计算
- 布尔值可以写判断
None使用前先判断:is None
多练几个接口返回数据、配置文件、用户列表的例子,你就能很自然地在项目中使用 JSON 了。
更多推荐
所有评论(0)