解析URL参数中的定界和嵌套字段名称以获得部分响应 [英] Parse delimited and nested field names from URL parameter for partial response
问题描述
在基于 Flask-RESTful
的API中,我想允许客户端通过?fields = ... 部分地检索JSON响应.
In a Flask-RESTful
based API, I want to allow clients to retrieve a JSON response partially, via the ?fields=...
parameter. It lists field names (keys of the JSON object) that will be used to construct a partial representation of the larger original.
这可能是最简单的逗号分隔列表:
This may be, in its simplest form, a comma-separated list:
GET /v1/foobar?fields=name,id,date
可以使用webargs的DelimitedList 架构字段很容易,对我来说没有问题.
That can be done with webargs' DelimitedList schema field easily, and is no trouble for me.
但是,为了允许表示嵌套对象的键,定界字段列表可能包括任意嵌套在匹配括号内的键:
But, to allow nested objects' keys to be represented, the delimited field list may include arbitrarily nested keys enclosed in matching parentheses:
GET /v1/foobar?fields=name,id,another(name,id),date
{
"name": "",
"id": "",
"another": {
"name": "",
"id": ""
},
"date": ""
}
GET /v1/foobar?fields=id,one(id,two(id,three(id),date)),date
{
"id": "",
"one": {
"id: "",
"two": {
"id": "",
"three": {
"id": ""
},
"date": ""
}
},
"date": ""
}
GET /v1/foobar?fields=just(me)
{
"just": {
"me: ""
}
}
我的问题有两个:
My question is two-fold:
-
是否可以通过本机的
webargs
和Marshmallow
来执行此操作(验证和反序列化)?
Is there a way to do this (validate & deserialize) with
webargs
andmarshmallow
natively?
如果没有,我该如何使用像 pyparsing
这样的解析框架来做到这一点?高度赞赏有关BNF语法的外观的任何提示.
If not, how would I do this with a parsing framework like pyparsing
? Any hint on what the BNF grammar is supposed to look like is highly appreciated.
推荐答案
Pyparsing具有几个有用的内置函数,分别是 delimitedList
和 nestedExpr
.这是一个带注释的代码段,可为您的值构建一个解析器.(我还提供了一个示例,其中您的列表元素可能不仅仅是简单的字母词):
Pyparsing has a couple of helpful built-ins, delimitedList
and nestedExpr
. Here is an annotated snippet that builds up a parser for your values. (I also included an example where your list elements might be more than just simple alphabetic words):
import pyparsing as pp
# placeholder element that will be used recursively
item = pp.Forward()
# your basic item type - expand as needed to include other characters or types
word = pp.Word(pp.alphas + '_')
list_element = word
# for instance, add support for numeric values
list_element = word | pp.pyparsing_common.number
# retain x(y, z, etc.) groupings using Group
grouped_item = pp.Group(word + pp.nestedExpr(content=pp.delimitedList(item)))
# define content for placeholder; must use '<<=' operator here, not '='
item <<= grouped_item | list_element
# create parser
parser = pp.Suppress("GET /v1/foobar?fields=") + pp.delimitedList(item)
您可以使用 runTests
测试任何pyparsing表达式:
You can test any pyparsing expression using runTests
:
parser.runTests("""
GET /v1/foobar?fields=name,id,date
GET /v1/foobar?fields=name,id,another(name,id),date
GET /v1/foobar?fields=id,one(id,two(id,three(id),date)),date
GET /v1/foobar?fields=just(me)
GET /v1/foobar?fields=numbers(1,2,3.7,-26e10)
""", fullDump=False)
赠予:
GET /v1/foobar?fields=name,id,date
['name', 'id', 'date']
GET /v1/foobar?fields=name,id,another(name,id),date
['name', 'id', ['another', ['name', 'id']], 'date']
GET /v1/foobar?fields=id,one(id,two(id,three(id),date)),date
['id', ['one', ['id', ['two', ['id', ['three', ['id']], 'date']]]], 'date']
GET /v1/foobar?fields=just(me)
[['just', ['me']]]
GET /v1/foobar?fields=numbers(1,2,3.7,-26e10)
[['numbers', [1, 2, 3.7, -260000000000.0]]]
这篇关于解析URL参数中的定界和嵌套字段名称以获得部分响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!