3

我有一个 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}"
}

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

URL 将爆炸,而且每次添加新查询参数时都需要更新架构。

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

4

2 回答 2

2

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

具体来说,请注意 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}"
        }
    ]
}

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

于 2013-08-29T17:53:12.943 回答
1

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

根据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/comments”。对于第二个链接,方法是“GET”(HTTP 的默认值),因此跟随此链接的客户端会将参数添加到 URL 以生成类似:“/15/comments?searchTerm=JSON&itemsPerPage=50”的内容。第三个链接定义了一个可能的交互,其中客户端将 POST 到 URI(例如“/15/comments”),其中 post-data 是新评论的 JSON 表示......

因此,您应该在链接的架构属性中描述查询参数。

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

于 2014-04-21T10:04:29.980 回答