【问题标题】:Root object or no? What is the best practice for API responses?根对象与否? API 响应的最佳实践是什么?
【发布时间】:2013-08-23 20:17:03
【问题描述】:

JSON 响应数据的最佳实践是什么,将对象嵌套在父对象中并包含根键路径?

{
    "activity": {
        "id": 20,
        "description": "a nice walk",
        "time_occurred": "2013-07-15T22:10:23Z",
        "duration": 45,
        "distance": 4.24,
        "location":"McDonalds"
    }
}

{
    "id": 20,
    "description": "a nice walk",
    "time_occurred": "2013-07-15T22:10:23Z",
    "duration": 45,
    "distance": 4.24,
    "location":"McDonalds"
}

似乎大多数 HTTP 框架(RestKit、GSON 等)都可以处理这两种情况,但我很想就哪种方法更好以及为什么有一个明确的答案。我觉得第一种方法更具描述性,这总是好的,但第二种方法更轻量级,您应该已经知道要根据 url 路径映射到哪个对象。

注意:我问的是移动应用后端的具体参考。

【问题讨论】:

  • 第二个。更少的代码来维护出去和回来。只有在有理由命名它或将它与某些东西分开时才添加额外的层。
  • 如果您的主要消费者是静态类型语言,我会考虑一些事情。我在这里写过它们:john-sheehan.com/blog/…

标签: android ios json api


【解决方案1】:

a) 描述资源/集合的根键

这具有响应中额外上下文的好处。根键描述资源或集合。我个人喜欢这种方法,因为它很明显 响应文档所描述的内容 - 您可能会争辩说它从端点很明显,但情况并非总是如此。

b) 没有描述资源/集合的根键

这种方法在野外更为常见。需要高可用性和快速的 API 通常会从响应文档中去除不必要的数据,以减少服务器负载和请求大小。其他人在设计自己的 API 时会考虑这种典型的流行 API,因此您会看到它是针对不在相同条件下运行的 API 进行模拟的。

我不同意缺少根密钥会使响应更易于使用的论点。从嵌套一层深的 JSON 对象中获取数据的工作量微不足道。

c) 根密钥是"data"

发布此问题时,JSON API specification 尚未达到 v1.0,这意味着可能会发生重大更改。如果您现在查看他们的(稳定的)规范,您会发现 their stance on the root key 已更改。

The proposal for v1.0 Release Candidate 2 changed the top-level key to "data".

主要资源现在必须出现在顶级 "data" 键下。

以这个单一资源为例

{
  "data": {
    "type": "articles",
    "id": "1",
    "attributes": {
      "title": "The best article of all time",
      "author": "Kanye West"
    }
 }

我找不到这背后的原因,但我怀疑这是因为一致性。无论是哪种资源,都可以从文档响应中获取数据,因为顶级成员是一致的,假设 API 遵循 JSON API v1.0 规范。

【讨论】:

    【解决方案2】:

    看起来双方都有牵引力。

    有利于根元素

    根据 JSONAPI.org

    它的根密钥必须与服务器对集合的 GET 请求的响应中提供的根密钥相同。

    例如,假设以下请求收集照片:

    GET /photos
    
    HTTP/1.1 200 OK
    Content-Type: application/json
    
    {
      "photos": [{
        "id": "1",
        "title": "Mustaches on a Stick"
      }]
    }
    

    支持无根元素

    Twitter 在使用 settings 对象时不会

    {
        "always_use_https": true, 
        "discoverable_by_email": true, 
        "geo_enabled": true, 
        "language": "en", 
        "protected": false, 
        "screen_name": "theSeanCook", 
        "show_all_inline_media": false, 
        "sleep_time": {
            "enabled": false, 
            "end_time": null, 
            "start_time": null
        }, 
        "time_zone": {
            "name": "Pacific Time (US & Canada)", 
            "tzinfo_name": "America/Los_Angeles", 
            "utc_offset": -28800
        }, 
        "trend_location": [
            {
                "country": "United States", 
                "countryCode": "US", 
                "name": "Atlanta", 
                "parentid": 23424977, 
                "placeType": {
                    "code": 7, 
                    "name": "Town"
                }, 
                "url": "http://where.yahooapis.com/v1/place/2357024", 
                "woeid": 2357024
            }
        ], 
        "use_cookie_personalization": true
    }
    

    Instagram 使用数据和元数据的组合,但不使用根 用户 对象

    {
      "meta":  {
        "code": 200
      },
      "data":  {
        "username": "obama",
        "bio": "",
        "website": "",
        "profile_picture": "http://images.ak.instagram.com/profiles/anonymousUser.jpg",
        "full_name": "",
        "counts":  {
          "media": 30,
          "followed_by": 113,
          "follows": 130
        },
        "id": "2082346"
      }
    }
    

    【讨论】:

    • “哪种方法更好,为什么”我认为你没有解释。
    • @BenMezger 我不知道为什么。我只是为论点的任何一方添加一些支持。看起来 JSONAPI.org 说保留根元素,而大多数其他 api 不使用它。
    • 在这种情况下没有“更好”或“最好”。这纯粹是一种味道
    【解决方案3】:

    当您从外部来源(或任何地方)接收到一个对象时,一切皆有可能。您需要检查该对象以了解如何以及是否可以使用它。

    保持简单。

    Twitter 的 API 比 Facebook 的 API 更易于使用,因为当您获得结果时,您几乎不必对它进行空值检查。

    考虑这段代码:

    推特:

    if (result.profile_image_url) {
        // use it
    }
    

    对比。脸书:

    if (result.data && result.data.picture && result.data.picture.url) {
       // use it
    }
    

    IMO,更好的解决方案很明确。根对象没有任何问题,但您的 API 应该让客户端使用起来简单易行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-09-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-07
      • 2018-09-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多