{JSON:API} 入门教程
22

file

JSON API 起初是由 Yehuda Katz 于2013年3月起草并于2015年3月达到稳定版本,它能让你的 API 调用充满效率。你可以按你所需接收数据,随着需求的改变添加、移除属性或关系。这最大限度减少了数据量和编写API调用接口的周期。

{json:api}

JSON API 文件工作原理跟其他任何 API 格式一样,你发送一个请求到一个终端然后接收你的文件。JSON API 文件定义了资源是如何组织的。这种组织形式有助于标准化你调用API的方式。

例如,当你通过一个简单的 GET 请求调用  articles 资源。

GET /articles HTTP/1.1
Accept: application/vnd.api+json

你接收到的响应看起来大概是这样子的:

// ...
{
    "type": "articles",
    "id": "1",
    "attributes": {
        "title": "Rails is Omakase"
    },
    "relationships": {
        "author": {
            "links": {
                "self": "http://example.com/articles/1/relationships/author",
                "related": "http://example.com/articles/1/author"
            },
            "data": {
                "type": "people",
                "id": "9"
            }
        }
    },
    "links": {
        "self": "http://example.com/articles/1"
    }
} // ...

看起来足够简单明了。author relationship 包含了自身关系 self 的链接和有关关联的一些基本信息。使用文件里面的链接,你可以从关联资源检索信息。

但这些仅仅谈及表面的功能。还有一些功能让JSON API使用起来非常友好。

复合文件

为了减少 HTTP 请求数,服务器 可能 允许请求主资源包含关联资源的响应。这种响应就叫做 「复合文件」

复合文件是包含了含有关联关系的数据。例如,当请求一篇如先前例子所示的文章,它可能包含作者的数据,所以你不需要第二次调用来接收文章作者的信息。

从它的一些用处来看,这是非常棒的。一次调用就能获取你想要的资源的全部数据,这是闻所未闻的,除非指定终端是已经编码好的。对于服务端处理来说,缓存和验证一次这样的请求是很容易的。

让我们来看一下这个例子,它返回一个文件的集合。

{
    "data": [{
        "type": "articles",
        "id": "1",
        "attributes": {
            "title": "JSON API paints my bikeshed!"
        },
        "links": {
            "self": "http://example.com/articles/1"
        },
        "relationships": {
            "author": {
                "links": {
                    "self": "http://example.com/articles/1/relationships/author",
                    "related": "http://example.com/articles/1/author"
                },
                "data": {
                    "type": "people",
                    "id": "9"
                }
            },
            "comments": {
                "links": {
                    "self": "http://example.com/articles/1/relationships/comments",
                    "related": "http://example.com/articles/1/comments"
                },
                "data": [{
                    "type": "comments",
                    "id": "5"
                }, {
                    "type": "comments",
                    "id": "12"
                }]
            }
        }
    }],
    "included": [{
        "type": "people",
        "id": "9",
        "attributes": {
            "first-name": "Dan",
            "last-name": "Gebhardt",
            "twitter": "dgeb"
        },
        "links": {
            "self": "http://example.com/people/9"
        }
    }, {
        "type": "comments",
        "id": "5",
        "attributes": {
            "body": "First!"
        },
        "relationships": {
            "author": {
                "data": {
                    "type": "people",
                    "id": "2"
                }
            }
        },
        "links": {
            "self": "http://example.com/comments/5"
        }
    }, {
        "type": "comments",
        "id": "12",
        "attributes": {
            "body": "I like XML better"
        },
        "relationships": {
            "author": {
                "data": {
                    "type": "people",
                    "id": "9"
                }
            }
        },
        "links": {
            "self": "http://example.com/comments/12"
        }
    }]
}

如果你查看 included 属性,你会看到文章的所有关联资源。每一个内含的文件中都有一个定义资源返回哪种类型的 type 属性以及一个终端获取文件所对应的链接。

article 中,仅通过 idtype 来指向 author 关联以及从 included 标签来加载相关的 people ,这看起来有点怪怪的。但是,想象一下,当有很多文章指向同一个 author ,文件仅需要在 included 数据中引用 people 一次。相当有效率!

内联资源

在上面的示例中,服务器在响应中包括所有关系,但是默认情况下您可能不希望这样,因为这会使响应有点膨胀。为此,规范提供了一种指定响应中应包含哪些关系的方法。

例如,如果您只需要 author 包含的关系,则可以使用 include 请求参数调用。这将告诉服务器仅发送与响应的指定关系。

GET /articles/1?include=author HTTP/1.1
Accept: application/vnd.api+json

如果您需要多个关系,可以使用逗号 (,) 。
当定义包含时,您可以更进一步并包含嵌套关系。例如,你想 comments 用 comments 中的  authors ,你可以用 comments.author:

GET /articles/1?include=author,comments.author HTTP/1.1
Accept: application/vnd.api+json

这种灵活性使得获取正确的资源变得轻而易举,使您可以根据需要调整结果。

稀疏属性

当你使用复合文件时,你的请求可能会变得大且快。尤其是这些请求包含关系中涉及大量数据时。大多数时候你无需在资源中定义每个属性,可你需要诸如作者名字之类的内容。JSON API 为此提供了稀疏属性。

你可以通过设置 fields 请求参数来指定欲获取的字段。格式为 fields[TYPE],这样你就可以为每种资源类型指定所需的字段。

GET /articles?include=author&fields[articles]=title,body&fields[people]=name HTTP/1.1
Accept: application/vnd.api+json

这个请求可囊括 articles 资源中的 title 和 body 字段,以及 people 资源中的name字段。

其他功能

服务端还可以定义更多的功能,这些功能包括排序,分页和过滤。

排序

如果服务端已实现,你可以通过 sort 请求参数对记录进行排序。 默认按照升序排序,你可以通过在字段前加上 - 表示降序排序。

GET /articles?sort=-created,title HTTP/1.1
Accept: application/vnd.api+json

分页

如果服务端支持分页,他将提供一些分页相关的额外元数据。 服务端可以决定如何来分页,可以通过偏移量,或者直接使用页数。 下面的例子中提供了其他页面所需的链接,在 mata 标签中还包含一些其他的元数据。

{
  links: {
    first: "http://example.com/articles?page=1",
    last: "http://example.com/articles?page=262",
    prev: "http://example.com/articles?page=261",
    next: null
  },
  meta: {
    current_page: 262,
    from: 3916,
    last_page: 262,
    per_page: 15,
    to: 3924,
    total: 3924
  }
}

过滤

该规范对过滤几乎没有说明,只是声明一个名为 filter 的参数,用于在服务器上实现过滤。该实现和具体服务器有关,可以是任何东西。

创建,更新和删除资源

了解文档结构后,创建和更新资源变得轻而易举。它使用标准HTTP谓词来传递请求所需的操作。用于查询的 GET ,用于创建的 POST ,用于(部分)更新的 PATCH 和用于删除资源的 DELETE

创建资源

POST /photos HTTP/1.1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json

{
  "data": {
    "type": "photos",
    "attributes": {
      "title": "Ember Hamster",
      "src": "http://example.com/images/productivity.png"
    },
    "relationships": {
      "photographer": {
        "data": { "type": "people", "id": "9" }
      }
    }
  }
}

这是一个发布新照片的示例。正如您所注意的那样,关系包含在请求中的 relationships 属性中。

更新资源

PATCH /articles/1 HTTP/1.1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json

{
  "data": {
    "type": "articles",
    "id": "1",
    "attributes": {
      "title": "To TDD or Not"
    }
  }
}

更新资源时,会将请求的字段更新为新值。未包含在请求中的字段不会被更新。

更新关系

可以通过两种方式更新关系。一种是在 PATCH 请求中包含关系, 就想你之前看到的一样;另一种方式是使用指定关系端点。

PATCH /articles/1/relationships/author HTTP/1.1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json

{
  "data": { "type": "people", "id": "12" }
}

这个请求会更新 article 上的一对一关系。如果您想删除关系,传递 null 即可。

如果要更新多对多关系,只需要将关系数据发送到短点即可。会将所有的成员的关系替换为您请求的数据。

PATCH /articles/1/relationships/tags HTTP/1.1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json

{
  "data": [
    { "type": "tags", "id": "2" },
    { "type": "tags", "id": "3" }
  ]
}

清除多对多的关系时,只需要将空数组作为数据请求即可。

删除资源

关于删除资源无需赘言,你只需向终端发送一个 DELETE 请求。

DELETE /photos/1 HTTP/1.1
Accept: application/vnd.api+json

了解更多

==========

如果你想了解关于 {json:api} 的细节和使用方法,请查阅 jsonapi.org。他们的标准相当清晰,尽管有许多特性不强求服务端去实现。在他们的网站上,他们也维护了一个 实现 JSON API 的服务端和客户端 清单,它可以帮助你快速在应用中实现。

他们正在制定 1.1 版本的标准,该版本会 100% 兼容 1.0 版本,相对于旧版本,1.1 版本只添加了新的特性,而没有对现有标准进行修改。

{json:api} <3

但愿你已经了解了这个标准为何如此优秀。个人而言,我喜欢它的结构,一致性以及灵活性,它使与 API 交互更加简单。你会一直清楚自己会得到什么,而无需承担请求数据的压力。

正因如此,我们正在开发 将远程 {json:api} 资源映射到 Laravel Eloquent 的扩展,就像模型和集合,和一个使用 Eloquent 模型生成 {json:api} 的扩展


Practice makes perfect.

原文地址:https://laravel-news.com/json-api-introd...

译文地址:https://laravel-china.org/topics/18561

本帖已被设为精华帖!
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 1
liyu001989

tips: fractal 支持 json-api,所以如果使用的是 dingo/api 可以一键切换

https://fractal.thephpleague.com/serializers/

1个月前

  • 请注意单词拼写,以及中英文排版,参考此页
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`, 更多语法请见这里 Markdown 语法
  • 支持表情,使用方法请见 Emoji 自动补全来咯,可用的 Emoji 请见 :metal: :point_right: Emoji 列表 :star: :sparkles:
  • 上传图片, 支持拖拽和剪切板黏贴上传, 格式限制 - jpg, png, gif
  • 发布框支持本地存储功能,会在内容变更时保存,「提交」按钮点击时清空
  请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!