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 里布尔值是小写的 truefalse

Python 里布尔值是首字母大写的 TrueFalse

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 字符串实现简单配置管理

这个案例会串联前面的知识点:

  1. 加载一个配置 JSON 字符串。
  2. 配置中同时包含对象、数组、字符串、数字、布尔值、null。
  3. 验证加载后的 Python 类型。
  4. 读取配置。
  5. 修改配置。
  6. 处理 JSON 格式错误。
  7. 演示中文输出不乱码。

案例完整代码

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
  • "文本" -> str
  • 123 -> int
  • 3.14 -> float
  • true / false -> bool
  • null -> None

实际使用时,先判断类型,再用对应方式操作:

  • 字典用键访问:data["name"]
  • 列表用索引或循环:data[0]for item in data
  • 字符串用字符串方法:strip()upper()
  • 数字可以计算
  • 布尔值可以写判断
  • None 使用前先判断:is None

多练几个接口返回数据、配置文件、用户列表的例子,你就能很自然地在项目中使用 JSON 了。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐