我与 JSON Server 的爱恨情仇

304 阅读6分钟

前言

首先介绍一下今天的主角:

JSON Server

JSON Server 是一个由 Typicode 创建的开源项目,旨在帮助开发者快速创建一个全功能的 REST API 以进行原型开发和前端测试。JSON Server 的主要特点在于其简单易用,只需一个 JSON 文件就可以生成一个完整的 RESTful API。

功能特性

  1. 快速上手: JSON Server 可以在几分钟内启动一个完整的 REST API 服务,无需复杂的配置。你只需要创建一个包含数据的 JSON 文件,并运行几条命令。

  2. 灵活的数据结构: JSON 文件中的数据结构可以任意定义。JSON Server 会自动将 JSON 文件中的数据映射为 RESTful 资源,可以进行常见的 CRUD(创建、读取、更新、删除)操作。

  3. 支持常见的 HTTP 方法: JSON Server 支持 GET、POST、PUT、PATCH 和 DELETE 等常见的 HTTP 方法,让你可以对资源进行各种操作。

  4. 支持查询参数: JSON Server 内置了对查询参数的支持,可以方便地对资源进行筛选、排序和分页操作。

  5. 可扩展: JSON Server 支持通过自定义中间件、路由和配置来扩展其功能,满足更复杂的需求。

安装与使用

安装

JSON Server 是一个基于 Node.js 的工具,因此需要先安装 Node.js 和 npm。然后可以通过 npm 安装 JSON Server:

npm install -g json-server
创建 JSON 文件

创建一个 db.json 文件,并在其中定义你的数据。例如:

{
  "posts": [
    { "id": 1, "title": "Hello World" },
    { "id": 2, "title": "JSON Server" }
  ],
  "comments": [
    { "id": 1, "body": "Nice post!", "postId": 1 }
  ]
}
启动服务器

在终端中运行以下命令来启动 JSON Server:

json-server --watch db.json

默认情况下,JSON Server 会在 http://localhost:3000 上启动服务器。

基础运用

假设你已经启动了 JSON Server,你可以进行以下操作:

  • 获取所有帖子

    GET /posts
    
  • 获取单个帖子

    GET /posts/1
    
  • 创建一个新帖子

    POST /posts
    Content-Type: application/json
    
    {
      "title": "New Post"
    }
    
  • 更新一个帖子

    PUT /posts/1
    Content-Type: application/json
    
    {
      "title": "Updated Post"
    }
    
  • 删除一个帖子

    DELETE /posts/1
    

    是不是看起来怪厉害的?确实,但是第一次用坑我一下也挺难绷的...

JavaScript 中的 ===== 的区别

做前端开发的肯定不陌生这个东西,这里简单复盘一下:

===== 都是用于比较的运算符,但它们有不同的行为。

  1. ==(相等运算符):

    • == 运算符会进行类型转换(Type Coercion),然后比较两个值。如果两个值在类型转换后相等,则返回 true
    • 例如:
      1 == '1' // true
      
  2. ===(严格相等运算符):

    • === 运算符不会进行类型转换,只有当两个值在不进行任何类型转换的情况下相等时,才会返回 true
    • 例如:
      1 === '1' // false
      

因此,当两个内容相同的数值(比如都为 1)使用这两种运算符进行对比时得到不同的结果,原因通常是因为类型不同。如果两个数值都是同一类型(如都是数字类型),那么 ===== 都会返回相同的结果:

1 == 1 // true
1 === 1 // true

但是如果它们的类型不同,例如一个是数字类型,一个是字符串类型:

1 == '1' // true,因为 '1' 会被转换成数字 1
1 === '1' // false,因为它们类型不同,一个是数字类型,一个是字符串类型

乍一看是不是有点蒙,这两个东西放在一起能有啥神奇的事情么?要不是亲身经历还真就不知道还能有这样的乌龙。。

正文启动!

首先我使用了这样的一份文件作为 JSON Server 的数据源:

{
  "users": [
    {
      "id": 1,
      "name": "高修文"
    },
    {
      "id": 2,
      "name": "熊天成"
    },
    {
      "id": 3,
      "name": "郑华"
    },
    {
      "id": 4,
      "name": "王文静"
    }
  ],
  "projects": [
    {
      "id": 1,
      "name": "骑手管理",
      "personId": 1,
      "organization": "外卖组",
      "created": 1604989757139
    },
    {
      "id": 2,
      "name": "团购 APP",
      "personId": 2,
      "organization": "团购组",
      "created": 1604989757139
    },
    {
      "id": 3,
      "name": "物料管理系统",
      "personId": 2,
      "organization": "物料组",
      "created": 1546300800000
    },
    {
      "id": 4,
      "name": "总部管理系统",
      "personId": 3,
      "organization": "总部",
      "created": 1604980000011
    },
    {
      "id": 5,
      "name": "送餐路线规划系统",
      "personId": 4,
      "organization": "外卖组",
      "created": 1546900800000
    }
  ]
}

我们可以注意到,users中的id字段与projects中的personIdid字段都是int类型的(划重点,后面要考)。

同时,我编写了一个用于处理并显示列表的组件:

export const List = ({list, users}) => {
  return <table>
    <thead>
    <tr>
      <th>名称</th>
      <th>负责人</th>
    </tr>
    </thead>
    <tbody>
    {
      list.map(project => <tr key={project.id}>
        <td>{project.name}</td>
        <td>{users.find(user => user.id === project.personId)?.name || "未知"}</td>
      </tr>)
    }
    </tbody>
  </table>
}

屏幕前的你是不是觉得他应该这样显示呢:

截屏2024-07-24 18.39.56.png

可惜并不是,它是这样的:

截屏2024-07-24 18.40.58.png

注:数据我并不是直接喂给组件进行处理的,而是通过 JSON Server 模拟一个后端服务进行传递的,因为后面还需要写其他的内容,直接通过代码侵入的方式模拟数据是非常不好的做法。

问题就在这里,JSON Server 传递信息的时候是按照提供的数据源原样传递的吗?

我尝试访问了其启动后提供的两个链接。得到了如下结果:

http://localhost:3001/users

[
    {
        "id": "1",
        "name": "高修文"
    },
    {
        "id": "2",
        "name": "熊天成"
    },
    {
        "id": "3",
        "name": "郑华"
    },
    {
        "id": "4",
        "name": "王文静"
    }
]

http://localhost:3001/projects

[
    {
        "id": "1",
        "name": "骑手管理",
        "personId": 1,
        "organization": "外卖组",
        "created": 1604989757139
    },
    {
        "id": "2",
        "name": "团购 APP",
        "personId": 2,
        "organization": "团购组",
        "created": 1604989757139
    },
    {
        "id": "3",
        "name": "物料管理系统",
        "personId": 2,
        "organization": "物料组",
        "created": 1546300800000
    },
    {
        "id": "4",
        "name": "总部管理系统",
        "personId": 3,
        "organization": "总部",
        "created": 1604980000011
    },
    {
        "id": "5",
        "name": "送餐路线规划系统",
        "personId": 4,
        "organization": "外卖组",
        "created": 1546900800000
    }
]

细心的你已经发现了,JSON Server 将两个接口的id字段从int类型改成了string类型。

这也就造成了上图中出现的负责人一栏全为未知的情况。

当我们在使用===进行比较时,user.id在前端处理数据时,其是作为string类型进行处理的,而project.personId在前端却是int类型。三等号在比较左右两侧内容时,会要求内容和类型同时相等,显然这两个字段的类型是不同的,所以出现了上图的问题。解决方法自然也是非常简单,直接改用==就好了。

一开始我并没有想到 JSON Server 会在这里偷袭我一下,甚至还在怀疑我学的 JS 是不是假的😂。这件事告诉我们出现问题的时候要检查每一处内容,避免内鬼出现。