ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Himalaya 3.0 `--json` 输出键全面切换 camelCase:一次针对脚本消费方的破坏性契约变更解读

Himalaya 3.0 `--json` 输出键全面切换 camelCase:一次针对脚本消费方的破坏性契约变更解读 CLI【免费下载链接】himalayaCLI to manage emails项目地址https://gitcode.com/gh_mirrors/hi/himalaya点击查看免费下载导读本文基于 Himalaya 仓库中的变更提案 cairn/changes/json-keys-are-camel-case/proposal.md 及其配套的 delta.md 与 tasks.md完整解读 Himalaya 计划在 3.0 版本中把--json输出对象键从 kebab-case / snake_case 混用统一为 camelCase 的破坏性变更包括动机、影响面、明确不动的地方、以及 alias 陷阱。读完本文你将理解这次变更为什么必须放在大版本、哪些输出类型会被改写、哪些拼写会被刻意保留以及作为脚本或下游 JSON Schema 消费者需要如何准备迁移。一、为什么--json键必须改为 camelCase1. Pimalaya 家族已经统一约定Himalaya 是 Pimalaya 家族的四个产品之一。该家族早已把--json的对象键标准化为 camelCase但 Himalaya 由于历史原因无法立即跟进——这个提案就是消除这项差异的正式计划。2. 上游线上格式本来就讲 camelCase提案中的第一个理由是camelCase 正是这些命令所包装的线上格式已经使用的语言。JMAP 对象按 RFC 8620 本身就是 camelCaseMicrosoft Graph 的响应是 camelCaseHimalaya 对接的每一个 Google APIGmail REST也是 camelCase。也就是说一个 Gmail 或 Graph 响应在流入 Himalaya 的输出类型时会无缘无故地跨过一次大小写边界——而这只是因为 serde 的默认行为Rust 字段名messages_total默认序列化为 snake_casemessages_total没有其他理由。3. 脚本消费方的点访问痛点第二个理由是--json存在的意义——被脚本消费。而无论是 jq 还是 JavaScript都无法对包含连字符的键使用点访问jq 中.messages-total必须写成.messages-totalJavaScript 中必须写成obj[messages-total]更危险的是脚本一旦忘记加引号失败是静默的返回null而非报错而不是响亮地暴露问题。而messagesTotal在两种语言中都可以直接点访问、语义一致。camelCase 因此是脚本消费场景下唯一让键可点访问的命名方案。二、现状一个 CLI 里并存两套命名约定提案明确指出Himalaya 今天输出的并不是一种约定而是两种。1. 26 个类型带着#[serde(rename_all kebab-case)]以下类型按提案原文列举均已在本仓库源码中核实显式声明了 kebab-case 序列化分类文件Gmail / Graph profilesrc/gmail/profile/get.rs、src/msgraph/profile/get.rsGmail historysrc/gmail/history/list.rs含GmailHistoryListOutput、GmailHistoryRecordOutput、GmailHistoryMessageOutput、GmailHistoryLabelOutput三个 Gmail get 渲染器src/gmail/messages/get.rs、src/gmail/drafts/get.rs、src/gmail/threads/get.rs五个 Gmail settings 单例src/gmail/settings/pop/get.rs、src/gmail/settings/autoforwarding/get.rs、src/gmail/settings/language/get.rs、src/gmail/settings/vacation/get.rs、src/gmail/settings/imap/get.rsManageSievesrc/sieve/get.rs、src/sieve/list.rs、src/sieve/capability.rsIMAPsrc/imap/id.rsServerIdTable共享消息删除src/shared/message/delete.rsDeleteReport与DeleteAction共享邮件领域类型src/email/envelope.rsEnvelope、src/email/mailbox.rsMailbox、src/email/flag.rs、src/email/address.rs2. 其余类型不带注解走 serde 默认的 snake_case未带rename_all的类型直接按 Rust 字段名输出 snake_case。于是同一个 CLI 中出现了典型的精神分裂输出src/shared/output.rs 中PaginatedT的分页字段next_page输出为next_pagesnake_case而gmail profile get的messages_total字段因为 kebab-case 注解输出为messages-total。两者并排出现在同一个 Himalaya CLI 的--json输出里对消费方毫无规律可循。3. 版本契约为什么必须等 3.0Himalaya 当前版本为 2.1.0见 Cargo.toml。--json的键是已发布给用户的公开契约改变它们是破坏性变更因此必须留到 3.0 大版本发布。这也是整个提案的时间线前提。三、3.0 到底改什么1. 只动输出类型不碰其他变更范围被严格限定在输出类型即交给printer.out的类型以及注册在 src/json_schema.rs 中的类型。具体做法是每个输出类型加上#[serde(rename_all camelCase)]移除这些类型上现有的 kebab-case 重命名。2. 参考类型GmailProfileOutput提案指定的参考类型是 src/gmail/profile/get.rs 中的GmailProfileOutput。它的载荷将发生如下变化{email, messages-total, threads-total, history-id} ↓ {email, messagesTotal, threadsTotal, historyId}注意该类型当前的文档注释写的是旧拼写{email, messages-total, threads-total, history-id}在 3.0 中命名旧拼写的文档注释也要随之更新——这是任务清单里明确列出的一项Update the doc comments naming a key spelling, starting with GmailProfileOutput。3. 另一半清理统一*Output后缀注册在src/json_schema.rs中的类型共有61 个其中19 个已经带*Output后缀42 个没有如Envelopes、Mailboxes、MessagesTable、DeleteReport、SieveScripts等。把它们统一重命名为*Output是同一清理的另一半必须放在同一个大版本中完成——因为两件事改动的是同一批声明。参考命名同样是GmailProfileOutput。4. 源码中的注册表实况src/json_schema.rs 的schemas()函数以himalaya-命令路径为键注册每个命令的--jsonpayload 类型共享 APIhimalaya-mailbox-list→Mailboxes、himalaya-envelope-list/himalaya-envelope-search→Envelopes、himalaya-message-delete→DeleteReport等协议专属himalaya-imap-id→ServerIdTable、himalaya-sieve-get→SieveScriptOutput、himalaya-gmail-profile-get→GmailProfileOutput、himalaya-msgraph-messages-get→MsgraphMessageGetOutput等分页列表使用PaginatedT包装因此next_page字段也会被 schema 描述出来。这与 cairn/spec/commands.md 中--json切换每个命令到 JSON数据通过 printer 输出到 stdout的规范相互印证。四、三处刻意不动的地方提案特别强调以下三件事故意保留原样不是遗漏而是边界。1. 配置类型保持 kebab-casesrc/config.rs 中的Config及大量子类型如 EnvelopeConfig、MailboxConfig使用#[serde(rename_all kebab-case)]多数还带deny_unknown_fields从TOML反序列化。原因很直接TOML 中连字符键是家族约定且没有任何 jq 表达式会接触到配置。这条规则只约束 printer 发出的内容从不约束 loader 读取的内容——输出端的事与输入端无关。2. Provider 透传字段保留自己的拼写携带线上原始名称的字段会保留其显式的#[serde(rename ...)]odata.nextLink是 Microsoft Graph 的原名nextPageToken是 Gmail 的原名。这两者都不是能从 Rust 字段名推导出来的拼写。对持有这类字段的类型应用rename_all不会触碰它们rename优先于rename_all这恰好是正确的行为——并且提案明确警告未来也不应有人去修正它们。这些 rename 位于 io-gmail / io-msgraph 依赖 crate 的资源类型中Himalaya 仓库内没有对应字面量。3. io-gmail / io-msgraph 之上的透明 newtype 不归 Himalaya 改MsgraphMessageGetOutputsrc/msgraph/messages/get.rs以及 Gmail settings 的 newtype是#[serde(transparent)]的透明包装序列化的是 io- crate 声明的资源——而这些资源本身就已经是 provider 的 camelCase。它们不需要任何属性也不得被强制套上属性。这与 cairn/spec/commands.md 中get输出通过透明 newtype 原样发出list已序列化的后端资源的规范一致一行list读到的东西在get里形状必须完全相同。4. 但 Himalaya 自己的分页字段不是透传Paginated::next_pagesrc/shared/output.rs是Himalaya 自己发明的字段用于包装 provider 的游标而不是透传。因此它和任何其他输出字段一样在 3.0 变为nextPage。next_page → nextPage Himalaya 自有分页字段随大部队改 nextPageToken → nextPageToken Gmail 透传字段不动五、别名陷阱为什么serde(alias)救不了过渡期一个容易踩的坑#[serde(alias ...)]是仅用于反序列化的属性。它教Deserialize接受第二种拼写但对Serialize完全没有效果——因此它无法让一个输出类型在过渡期同时发出messages-total和messagesTotal。而输出类型只序列化、从不反序列化所以给输出类型加 alias 纯粹是装饰。如果将来想软化这次破坏提案列出了两条替代路径在 printer 里孪生键同时序列化两种拼写。代价是 payload 体积翻倍且发布的 schema 必须为同一个值描述两个名字接受大版本的破坏把键重命名当作 major release 中允许可见的变化。最终决策是接受破坏——大版本正是键重命名可以光明正大出现的地方。这也意味着从今天到 3.0messages-total等旧键不会获得任何双拼写兼容期。六、落地任务清单与验收标准配套的 tasks.md 给出了完整的执行清单当前处于Held until the 3.0 cycle opens状态给 src/json_schema.rs 注册的每一个类型加上#[serde(rename_all camelCase)]移除它替换掉的 26 处 kebab-case 重命名保留 provider 透传 renameodata.nextLink、nextPageToken以及 io-gmail / io-msgraph 资源之上的透明 newtype 不动保留 src/config.rs 的 kebab-case——TOML 键不是--json键把 42 个尚未带*Output后缀的注册类型重命名参考GmailProfileOutput更新命名了键拼写的文档注释从GmailProfileOutput开始重新生成 JSON Schema并检查没有任何键还保留连字符在 CHANGELOG 的 3.0 段落、Changed分类下按破坏性变更记录。对应的验收需求写入 delta.md每个交给 printer 的输出类型 SHALL 以 camelCase 序列化其键携带 provider 拼写的字段 SHALL 保留显式#[serde(rename)]配置类型 SHALL 保持 kebab-case。该 delta 将折叠进 cairn/spec/commands.md前提是 3.0 真正落地了重命名。七、影响面与迁移提示Out of scope提案最后划清了本次变更的边界没有 CHANGELOG 条目在 3.0 落地重命名之前对用户没有任何可见变化JSON Schema 文件随键改变json-schema命令src/cli.rs写出的 schema 文件会同步更新任何钉死在旧 schema 上的下游消费者需要在同一时间重新生成。对脚本开发者而言迁移要点可以概括为三句话3.0 之前继续使用.messages-total、obj[messages-total]这类带引号访问3.0 发布后所有 Himalaya 自有的输出键都变成可点访问的 camelCasemessagesTotal、nextPage等永远不要把odata.nextLink、nextPageToken这类 provider 透传键改成 camelCase——它们不是 Himalaya 的命名改名反而会破坏与上游 API 的对应关系。赞分享CLI【免费下载链接】himalayaCLI to manage emails项目地址https://gitcode.com/gh_mirrors/hi/himalaya点击查看免费下载相关推荐OpCore Simplify 新手指南如何 10 分钟生成 OpenCore EFI 的完整教程附避坑清单OpCore Simplify 新手指南如何 10 分钟生成 OpenCore EFI 的完整教程附避坑清单 在黑苹果的圈子里最劝退新手的从来不是下载系CLIRobot Framework 3.0 Alpha 1 版本全解读Python 3 支持、统一 robot 启动脚本与破坏性变更全景Robot Framework 3.0 Alpha 1 版本全解读Python 3 支持、统一 robot 启动脚本与破坏性变更全景 导读 Robot Fra测试RPA接口测试vault CLI 的 --json 输出规范全解析面向脚本、编辑器与 CI 的稳定 Schema 契约vault CLI 的 json 输出规范全解析面向脚本、编辑器与 CI 的稳定 Schema 契约 导读 vault 是 StaffML 题库工程vaul教育教程人工智能机器学习上一篇解决MudBlazor中Dialog嵌套Menu失效问题Provider加载顺序深度解析下一篇解决FanControl.CorsairLink插件风扇控制卡重复问题的3个实用方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表