【问题标题】:Preserving query parameters when paging jsonschema/hyperschema分页 jsonschema/hyperschema 时保留查询参数
【发布时间】:2013-08-27 22:36:49
【问题描述】:

我有一个 REST API,它有很多潜在的查询参数。

API 是通过像 http://example.com/api/object?someParam=10&someOtherParam=20 这样的 URL 访问的

存在大量潜在参数的地方。

响应定义如下:

{
    "title": "Object Collection",
    "type": "object",
    "properties": {
        "collection": {
            "title": "Collection",
            "type": "array",
            "items": {
                "$ref": "/schema/object.json"
            }
        },
        "currPage": {
            "title": "Current Page",
            "type": "int"
        },
        "nextPage": {
            "title": "Next Page",
            "type": "int"
        },
        "prevPage": {
            "title": "Previous Page",
            "type": "int"
        },
        "perPage": {
            "title": "Per Page",
            "type": "int"
        },
        "totalCount": {
            "title": "Total Count",
            "type": "integer"
        }
    },
    "links": [
        {
            "title": "Get object collection",
            "rel": "self",
            "method": "GET",
            "href": "/api/object?page={currPage}&perPage={perPage}"
        },
        {
            "title": "Get next page",
            "rel": "next",
            "method": "GET",
            "href": "/api/object?page={nextPage}&perPage={perPage}"
        },
        {
            "title": "Get prev page",
            "rel": "prev",
            "method": "GET",
            "href": "/api/object?page={prevPage}&perPage={perPage}"
        }
    ]
}

当然,当前定义的问题在于它在尝试通过链接转到另一个页面时会抛出查询参数。

有什么好方法可以解释任意数量的参数吗?

理论上,我可以将所有可能性添加到我的回复中,例如

"properties": {
    ...
    "someParam" : {
        "description": "Some Param"
    },
    "someOtherParam" : {
        "description": "Another param"
    }
}

让我的链接看起来像:

{
    "title": "Get prev page",
    "rel": "prev",
    "method": "GET",
    "href": "/api/object?page={prevPage}&perPage={perPage}&someParam={someParam}&someOtherParam={someOtherParam}"
}

但这很快就会变得很麻烦,尤其是考虑到大量的查询参数。

网址会爆炸,而且每次添加新的查询参数时都需要更新架构。

这让我觉得这是一个非常常见的用例,但经过大量的谷歌搜索后,我无法在上面找到任何东西。

【问题讨论】:

    标签: json rest pagination jsonschema


    【解决方案1】:

    所以,我选择了一种似乎行之有效的方法。可能有更好的解决方案,但这是我们能想到的唯一一个不会让人觉得很恶心的解决方案。

    具体来说,注意queryString的引入,以及它在链接中的使用。

    通过从传入的查询字符串中去除“page”和“perPage”字段来填充queryString,以免重复这些字段。

    另外值得注意的是 queryString 之前的 +,它可以防止它被 URL 编码。

    {
        "title": "Object Collection",
        "type": "object",
        "properties": {
            "collection": {
                "title": "Collection",
                "type": "array",
                "items": {
                    "$ref": "/schema/object.json"
                }
            },
            "currPage": {
                "title": "Current Page",
                "type": "int"
            },
            "nextPage": {
                "title": "Next Page",
                "type": "int"
            },
            "prevPage": {
                "title": "Previous Page",
                "type": "int"
            },
            "perPage": {
                "title": "Per Page",
                "type": "int"
            },
            "totalCount": {
                "title": "Total Count",
                "type": "integer"
            },
            //queryString is all of the GET parameters, in their URL form
            // e.g. "someParam=10&anotherParam=20"
            "queryString": {
                "title": "String representing the rest of the query params",
                "type": "string"
            }
        },
        "links": [
            //Added queryString to the end of the hrefs. + sign prevents URL encoding
            {
                "title": "Get object collection",
                "rel": "self",
                "method": "GET",
                "href": "/api/object?page={currPage}&perPage={perPage}&{+queryString}"
            },
            {
                "title": "Get next page",
                "rel": "next",
                "method": "GET",
                "href": "/api/object?page={nextPage}&perPage={perPage}&{+queryString}"
            },
            {
                "title": "Get prev page",
                "rel": "prev",
                "method": "GET",
                "href": "/api/object?page={prevPage}&perPage={perPage}&{+queryString}"
            }
        ]
    }
    

    希望其他人觉得这很有用。

    【讨论】:

    • 谢谢 :) 我将在我自己的 API 中窃取你的想法 :) 谢谢!
    【解决方案2】:

    只是为了让它保持在同一个线程中:)

    根据http://json-schema.org/latest/json-schema-hypermedia.html

    {
        "title": "News post",
        ...
        "links": [
            {
                "rel": "comments",
                "href": "/{id}/comments"
            },
            {
                "rel": "search",
                "href": "/{id}/comments",
                "schema": {
                    "type": "object",
                    "properties": {
                        "searchTerm": {
                            "type": "string"
                        },
                        "itemsPerPage": {
                            "type": "integer",
                            "minimum": 10,
                            "multipleOf": 10,
                            "default": 20
                        }
                    },
                    "required": ["searchTerm"]
                }
            },
            {
                "title": "Post a comment",
                "rel": "create",
                "href": "/{id}/comments",
                "method": "POST",
                "schema": {
                    "type": "object",
                    "properties": {
                        "message": {
                            "type": "string"
                        }
                    },
                    "required": ["message"]
                }
            }
        ]
    }
    

    如果客户端遵循第一个链接,则 URI 可能会扩展为 “/15/cmets”。对于第二个链接,方法是“GET”(默认 对于 HTTP),因此遵循此链接的客户端会将参数添加到 生成如下内容的 URL: “/15/cmets?searchTerm=JSON&itemsPerPage=50”。第三个链接定义 客户端将 POST 到 URI 的可能交互(例如 "/15/cmets"),其中 post-data 是 新评论...

    所以你应该在链接的模式属性中描述查询参数。

    因此,您可以在链接中引用的查询对象有一个单独的架构,这不需要通用架构中的其他属性。

    【讨论】:

      猜你喜欢
      • 2010-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-05
      • 2016-06-20
      • 1970-01-01
      • 2015-09-26
      • 2020-10-23
      相关资源
      最近更新 更多