在分页jsonschema / hyperschema时保留查询参数

时间:2013-08-27 22:36:50

标签: json rest pagination jsonschema

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

通过http://example.com/api/object?someParam=10&someOtherParam=20

等网址访问API

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

响应定义如下:

{
    "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}"
}

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

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

这让我觉得这是一个非常常见的用例,但是经过大量的谷歌搜索后,我找不到任何相关内容。

2 个答案:

答案 0 :(得分: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}"
        }
    ]
}

希望别人觉得这很有用。

答案 1 :(得分: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 /评论&#34 ;.对于第二个链接,方法是" GET" (默认值   对于HTTP)所以跟随此链接的客户端将添加参数   生成类似以下内容的URL:   " / 15 /注释= SEARCHTERM JSON&安培; itemsPerPage = 50&#34 ;.第三个链接定义   客户端POST到URI的可能交互(例如   " / 15 / comments"),其中后期数据是JSON的表示形式   新评论......

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

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