当前位置:首页 > 文章列表 > 文章 > php教程 > PHP 枚举序列化JSON 输出枚举值时为什么格式不一致怎样完成一个可复用的最小示例

PHP 枚举序列化JSON 输出枚举值时为什么格式不一致怎样完成一个可复用的最小示例

来源:17golang原创 2026-11-10 03:53:47 0浏览 收藏

接口里有一个状态字段时,PHP 枚举经常会出现“同样是 case,JSON 输出却不一样”的现象。原因不是 json_encode() 随机变化,而是纯枚举和 Backed Enum 的类型契约不同:纯枚举没有标量值,直接 JSON 序列化会报错;Backed Enum 默认输出它的 string 或 int 值。如果客户端还需要稳定拿到 case 名称,就应当显式实现 JsonSerializable。

官方手册:https://www.php.net/manual/en/language.enumerations.serialization.php

先确认接口要传“存储值”还是“可读名称”,再决定直接使用 Backed Enum 的默认输出,还是把 name 和 value 组装成固定对象。不要把 PHP 的内部 serialize() 结果当成对外 JSON 契约。

先分清两种枚举的默认输出

我排查这类问题时,会先看枚举声明有没有冒号和标量类型。只有 enum Status { ... } 的是纯枚举;写成 enum Status: string { ... } 或 enum Status: int { ... } 的是 Backed Enum。前者的 case 只有名称,后者还绑定了一个可用于传输或存储的标量值。

PHP 手册规定,Backed Enum 进入 json_encode() 时默认按其标量值表示;纯枚举直接进入 JSON 序列化则会抛出错误。两者都可以通过实现 JsonSerializable 改写这一默认行为。

Pure Enum 与 Backed Enum 经过 json_encode 后分别进入错误分支和标量值分支的静态关系说明图
图1:默认序列化结构说明图,查看纯枚举与 Backed Enum 的类型边界和 JSON 输出差异;不是运行截图。

用最小示例看见 JSON 输出边界

下面的示例故意把两个枚举放在同一个数组里,重点不是做完整接口,而是把默认契约摆在眼前。OrderState::Paid 是 Backed Enum,因此可以直接得到字符串值;Visibility::Public 是纯枚举,不能依赖默认 JSON 转换。

 OrderState::Paid,
    'visibility' => Visibility::Public,
];

// 对外接口不要把 serialize() 的内部格式当作 JSON 契约。
$json = json_encode($payload, JSON_THROW_ON_ERROR);
echo $json, PHP_EOL;

如果暂时移除 visibility,这个数组可以自然得到类似 {"state":"paid"} 的 JSON。加入纯枚举后,默认行为就不再是“自动输出 case 名称”,而是报错。这个差异解释了为什么某些接口只传出 paid,另一些接口却在序列化阶段失败。

用 JsonSerializable 固定接口对象

当客户端既要展示 Paid,又要提交稳定的 paid 时,最稳妥的做法不是让客户端猜测字段,而是让枚举明确返回对象。下面让 Backed Enum 自己实现 JsonSerializable,同时保留默认的 value 语义。

 $this->name,
            'value' => $this->value,
        ];
    }
}

// 外层业务对象保持普通数组,枚举负责自己的序列化契约。
$payload = ['status' => OrderStatus::Paid];
$json = json_encode($payload, JSON_THROW_ON_ERROR);
echo $json, PHP_EOL;

此时接口对象的形状可以稳定为 {"status":{"name":"Paid","value":"paid"}}。如果接口只需要数据库值,就不必为了展示名称而改变契约;可以在资源层显式使用 $status->value。如果还需要支持纯枚举,也可以让纯枚举实现同样的 JsonSerializable,返回只包含 name 的对象。

OrderStatus 的 name 和 value 通过 JsonSerializable 与 jsonSerialize 映射为稳定 API 对象的结构说明图
图2:自定义输出结构说明图,查看枚举名称和值如何汇聚到稳定的 API 对象;不是运行截图。

按接口契约选择字段并排查格式不一致

把选择落到项目里,可以按下面三种情况判断:

  • 数据库和接口都只认固定编码:使用 Backed Enum 的 value,保持字符串或整数类型不变。
  • 前端还要展示人类可读状态:实现 JsonSerializable,固定返回 name 与 value,不要让每个调用方自行拼装。
  • 枚举没有外部编码:不要假设纯枚举会自动变成名称;明确返回 $this->name 或一个带语义的对象。

遇到输出异常时,先检查枚举声明是否带 backed type,再查调用点是否把整个 case 传给 json_encode()。接着确认有没有实现 JsonSerializable,以及返回数组里的字段类型是否和旧客户端约定一致。最后区分 serialize() 与 json_encode():前者服务于 PHP 的序列化恢复,后者才是常见接口响应的 JSON 表示。

相关问题

为什么 Backed Enum 默认只输出 value?

因为 backed value 是枚举声明中明确绑定的标量,适合保持接口和存储字段的稳定类型。case 名称是否展示,应由接口契约显式决定。

纯枚举可以直接输出 case 名称吗?

不能依赖默认行为。纯枚举应实现 JsonSerializable,在 jsonSerialize() 中返回 $this->name 或结构化数组。

JsonSerializable 会影响 PHP 的 serialize() 吗?

它主要定义 JSON 序列化时返回的值,不等同于 PHP 内部的 serialize() 规则。两种序列化用途不同,应分别设计和测试。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
PHP Fibers怎样把阻塞任务封装成可恢复协程怎样在批处理代码中减少额外分配PHP Fibers怎样把阻塞任务封装成可恢复协程怎样在批处理代码中减少额外分配
上一篇
PHP Fibers怎样把阻塞任务封装成可恢复协程怎样在批处理代码中减少额外分配
PHP 枚举序列化JSON 输出枚举值时为什么格式不一致为什么结果为空或不符合预期
下一篇
PHP 枚举序列化JSON 输出枚举值时为什么格式不一致为什么结果为空或不符合预期
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    965次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    966次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    1077次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    1057次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    888次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码