You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Gatsby集合路由的jsonId值出现异常转换?

Gatsby集合路由中JSON ID自动转换为带连字符小写格式的问题

问题背景

使用gatsby-transformer-json插件查询JSON文件,项目目录结构如下:

src
├── data
│   ├── channels
│   │   └── UC7Lhhngb9lLW6tuPddEM62A.json
│   │   ...
│   └── videos
│       └── K17df81RL9Y.json
│   │   ...

视频JSON文件(src/data/videos/K17df81RL9Y.json)内容示例:

{
  "id": "K17df81RL9Y",
  "title": "AURORA - Cure For Me (Official Video)",
  "channelId": "UC7Lhhngb9lLW6tuPddEM62A",
  "publishedAt": "2021-07-08T17:00:10Z",
  "thumbnails": {
    "default": {
      "url": "https://i.ytimg.com/vi/K17df81RL9Y/default.jpg",
      "width": 120,
      "height": 90
    },
    ...
  }
}

在pages目录下创建了video/{VideosJson.jsonId}.js集合路由组件,代码如下:

import * as React from "react";

const VideoDetails = (params) => {
  return (
    <main>
      <p>My blog post contents will go here (eventually).</p>
      <pre>
        <code
          dangerouslySetInnerHTML={{
            __html: JSON.stringify(params, null, 2),
          }}
        />
      </pre>
    </main>
  );
};

export default VideoDetails;

但生成的页面路径中,原始ID K17df81RL9Y 被转换为 k17df81-rl-9-y(大写转小写,大写字母前添加连字符),组件接收的params核心内容如下:

{
  "path": "/video/k17df81-rl-9-y/",
  "pageContext": {
    "jsonId": "K17df81RL9Y",
    "__params": {
      "jsonId": "k17df81-rl-9-y"
    }
  },
  "params": {
    "jsonId": "k17df81-rl-9-y"
  }
}

集合路由官方文档未提及此行为,询问原因。

原因分析

这是Gatsby内置的**slug格式化(slugify)**机制导致的:

  • Gatsby在处理集合路由的动态参数时,会自动对参数值做标准化处理,生成符合URL规范的路径片段
  • 处理规则包括:将所有字母转为小写、在大写字母前插入连字符(拆分混合大小写的字符串)、移除或替换URL不允许的特殊字符
  • 目的是保证URL的可读性、兼容性,同时符合SEO最佳实践

注意:虽然路径和params中的jsonId是格式化后的slug,但pageContext中仍然保留了原始的jsonId值(即K17df81RL9Y),可以直接从pageContext获取原始ID使用。

解决方案(保留原始ID作为路径)

如果需要保留原始ID作为路径参数,不使用自动格式化的slug,可以放弃集合路由,改用gatsby-node.js中的createPage API手动创建页面:

  1. 创建gatsby-node.js文件,添加以下代码:
exports.createPages = async ({ graphql, actions }) => {
  const { createPage } = actions;
  // 查询所有视频JSON数据
  const queryResult = await graphql(`
    query GetAllVideos {
      allVideosJson {
        nodes {
          id
        }
      }
    }
  `);

  // 遍历每个视频,创建对应页面
  queryResult.data.allVideosJson.nodes.forEach(video => {
    createPage({
      path: `/video/${video.id}/`,
      component: require.resolve("./src/pages/video/[id].js"),
      context: {
        id: video.id,
      },
    });
  });
};
  1. 将原集合路由文件video/{VideosJson.jsonId}.js重命名为video/[id].js,并修改组件从pageContext获取原始ID:
import * as React from "react";

const VideoDetails = ({ pageContext }) => {
  const { id } = pageContext;
  return (
    <main>
      <p>视频ID:{id}</p>
      <pre>
        <code>{JSON.stringify(pageContext, null, 2)}</code>
      </pre>
    </main>
  );
};

export default VideoDetails;

内容的提问来源于stack exchange,提问作者Sergio Flores

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 23:45:41