0

我一直在尝试查找一些jsonpatch==1.16有关如何使 PATCH 路径不区分大小写的文档。问题是:

PATCH /users/123
[
    {"op": "add", "path": "/firstname", "value": "Spammer"}
]

似乎要求 DB (MySQL / MariaDB) 列也完全正确firstname,而不是例如Firstnameor FirstName。当我将 JSON 中的路径更改为/FirstNameDB 列时,补丁就可以正常工作。但我不确定在这种情况下您是否应该在 JSON 中使用 CamelCase?好像有点不标准。

我怎样才能jsonpatch至少不区分大小写?或者,是否有某种方法可以在中间插入一些映射,例如:

def users_mapping(self, path):
    select = {
        "/firstname": "FirstName",
        "/lastname": "last_name",  # Just an example
    }
    return select.get(path, None)

使用 Python 3.5、SQLAlchemy 1.1.13 和 Flask-SQLAlchemy 2.2

4

1 回答 1

1

嗯,答案是:是的,你可以添加映射。这是我的一些注释的实现:

端点处理程序(例如PATCH /news/123):

def patch(self, news_id):
    """Change an existing News item partially using an instruction-based JSON, 
    as defined by: https://tools.ietf.org/html/rfc6902
    """
    news_item = News.query.get_or_404(news_id)
    self.patch_item(news_item, request.get_json())
    db.session.commit()

    # asdict() comes from dictalchemy method make_class_dictable(news)
    return make_response(jsonify(news_item.asdict()), 200)

它调用的方法:

# news = the db.Model for News, from SQLAlchemy
# patchdata = the JSON from the request, like this:
# [{"op": "add", "path": "/title", "value": "Example"}]
def patch_item(self, news, patchdata, **kwargs):
    # Map the values to DB column names
    mapped_patchdata = []
    for p in patchdata:
        # Replace eg. /title with /Title
        p = self.patch_mapping(p)
        mapped_patchdata.append(p)

    # This follows the normal JsonPatch procedure
    data = news.asdict(exclude_pk=True, **kwargs)
    # The only difference is that I pass the mapped version of the list
    patch = JsonPatch(mapped_patchdata)
    data = patch.apply(data)
    news.fromdict(data)

以及映射实现:

def patch_mapping(self, patch):
    """This is used to map a patch "path" or "from" to a custom value.
    Useful for when the patch path/from is not the same as the DB column name.

    Eg.
    PATCH /news/123
    [{ "op": "move", "from": "/title", "path": "/author" }]

    If the News column is "Title", having "/title" would fail to patch 
    because the case does not match. So the mapping converts this:
        { "op": "move", "from": "/title", "path": "/author" }
    To this:
        { "op": "move", "from": "/Title", "path": "/Author" }
    """

    # You can define arbitrary column names here.
    # As long as the DB column is identical, the patch will work just fine.
    mapping = {
        "/title": "/Title",
        "/contents": "/Contents",
        "/author": "/Author"
    }

    mutable = deepcopy(patch)
    for prop in patch:
        if prop == "path" or prop == "from":
            mutable[prop] = mapping.get(patch[prop], None)
    return mutable
于 2017-09-08T21:51:20.413 回答