在 Python 中使用 GraphQL 过滤 JSON 数据
Posted
技术标签:
【中文标题】在 Python 中使用 GraphQL 过滤 JSON 数据【英文标题】:Using GraphQL to Filter a JSON Data in Python 【发布时间】:2021-01-06 22:18:26 【问题描述】:我在我的 python 项目中使用官方的 graphene
包。我有一个来自正在运行的 Docker 容器检查命令的巨大嵌套 JSON 数据,我想从中获取一些字段。我可以逐个选择所有这些字段并将它们添加到这样的字典中:
def ContainerConfigs(configs):
data =
data['Command'] = configs['Args'][-1]
data['Hostname'] = configs['Config']['Hostname']
data['Image'] = configs['Config']['Image']
data['Distro'] = configs['Config']['Labels']['org.label-schema.name']
data['WorkDir'] = configs['Config']['WorkingDir']
data['IPAddress'] = configs['NetworkSettings']['Networks']['bridge']['IPAddress']
return data
但这是一个弱解决方案。我认为可以使用 GraphQL 对其进行优化。没有服务器、请求和响应。我想创建它的Schema
类并发送参数(JSON 和查询)并让函数执行该查询并返回结果。像这样的:
import graphene
# I need to find this part of the code
# class Schema(..):
# ...
# class Query(...):
# ...
def ContainerConfigs(configs, query):
schema = graphene.Schema(query=Query)
# I need to find a way to pass the configs (Json data) to the Query class to
# execute the query_string on the data
query_string = """
query
Args
Config
Hostname
Image
WorkingDir
Label
org.label-schema.name
NetworkSettings
Networks
bridge
IPAddress
"""
result = schema.execute(query_string)
return result
【问题讨论】:
您遇到了什么具体问题?一旦你检索到这些数据,你最终会用它做什么? 我正在尝试对数据执行查询并回复结果。 这里对我来说不明显的另一件事是 GraphQL 查询的结果将具有与输入数据相同的“形状”;您必须使用相同的嵌套字典语法来访问它。这似乎不是一项适合我的明显技术。 没有服务器? schema 用于服务器...如果您知道它是如何工作的,您可以模拟响应,它只是 json(将您的 json 转换为所需的响应形状),也许可以使用一些石墨烯部件...但您不知道它是如何工作的,先学吧 @DavidMaze 所以,你的意思是最好使用上面的脚本逐个选择所有这些字段?我认为会有一种更好的优化方法来从 python 中的 JSON 数据中获取这些任意字段。我认为 GraphQL 在这种情况下会很有帮助。我已经搜索了很多,但找不到任何合适的结果。其中大部分是关于 GraphQL 在 Django 或 Flask 等 Web 框架中的使用。 【参考方案1】:这不是一个很好的技术匹配:您最终会以 GraphQL 语法重新创建大量 Docker API,并且在您查询后它仍然具有相同的嵌套字典布局。
原则上,您可以编写与Docker API 具有相同布局的 GraphQL 模式。架构是必需的;没有它你就无法进行 GraphQL 查询,但这基本上涉及在你的源代码中复制整个 Docker API 对象模型。这里要注意的另一件事是,对 GraphQL 查询的响应与查询具有相同的“形状”(例如,请参见 graphql.org 上的 Execution 页面)。
如果您完成了所有这些工作,并运行了您显示的 GraphQL 查询,您将获得类似的嵌套字典响应
result = schema.execute(query_string)
hostname = result.data['Config']['Hostname']
这并不比你已经拥有的更好。 (同样,请参阅 Graphene Execution 文档页面上的示例。)
如果您想提取这些数据并将其封装在某种对象中,您可以创建一个类来为您完成。我可能会这样写:
from collections import namedtuple
class ContainerConfigs(namedtuple('ContainerConfigs', ['command', 'hostname', ...])):
@classmethod
def from_docker_inspect(cls, configs):
return cls(
command=configs['Args'][-1],
hostname=configs['Config']['Hostname'],
...
)
info = ContainerConfigs.from_docker_inspect(configs)
print(f"container hostname (not generally useful): info.hostname")
【讨论】:
谢谢,让我更清楚地解释我的问题。想象一下,你有一个巨大的 JSON 数据。您需要返回该数据的 150 个字段中的 50 个。获得这 50 个字段的最佳方法是什么?您是逐个获取它们并将它们添加到五十行的字典中(例如 ->data = configs['something']
)还是做得更好?
如果 server 支持 GraphQL 端点,您只能请求这 50 个特定字段,但尝试运行 GraphQL 查询没有多大意义(没有解析器或其他行为)在您已有的 JSON 对象上。另一种方法可能是对象外观,它在其__init__
方法中获取 JSON blob,并使用其他方法从中返回特定属性。或者,只编写没有相应类的提取器函数。以上是关于在 Python 中使用 GraphQL 过滤 JSON 数据的主要内容,如果未能解决你的问题,请参考以下文章
如何使用`django-filters`编写将在整数字段上使用范围过滤器的GraphQL查询?
如何在 Sangria 中使用 graphql 查询过滤列表响应