首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >python response.json保留顺序

python response.json保留顺序
EN

Stack Overflow用户
提问于 2018-07-19 07:16:51
回答 2查看 1.8K关注 0票数 0

我有一个针对post调用返回的json对象。

代码语言:javascript
复制
r = requests.post("url", json=data)

我正在执行r.json()来获取json对象。但据我所知,它创建了一个无序的dict对象。我需要维护秩序。

我看到了这里描述的解决方案:Items in JSON object are out of order using "json.dumps"?

但我的挑战是,我的起点是一个响应对象。如何将其转换为保留顺序的json?

添加更多细节:

我的API调用返回一个如下形式的对象:

代码语言:javascript
复制
[{
    "key01": "value01",
    "key02": "value02",
    "keyN": "valueN"
},
{
    "key01": "value01",
    "key02": "value02",
    "keyN": "valueN"
},
{
    "key01": "value01",
    "key02": "value02",
    "keyN": "valueN"
}
]

我有一个表,其中有三列: key01、key02和keyN。

我需要在一些小操作之后将这个json对象发布到一个维护key01、key02和keyN的特定顺序的软件。

但是,一旦我执行response.json(),它就会改变顺序。我尝试使用orderedlist方法,就像在另外两个线程中提到的那样,但是到目前为止,我的对象看起来是这样的:

代码语言:javascript
复制
b"OrderedDict([('key01','value01'),('key02','value02'),('keyN','valueN')])

我如何才能得到一个看起来像这样的json:{"key01":"value01","key02":"value02","keyN":"valueN"}

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-07-19 07:49:43

这些请求没有最好的文档,但通过阅读其源代码on the .json() method,我们可以看到它的定义如下:

代码语言:javascript
复制
def json(self, **kwargs):
    r"""Returns the json-encoded content of a response, if any.
    :param \*\*kwargs: Optional arguments that ``json.loads`` takes.
    :raises ValueError: If the response body does not contain valid json.
    """

    if not self.encoding and self.content and len(self.content) > 3:
        # No encoding set. JSON RFC 4627 section 3 states we should expect
        # UTF-8, -16 or -32. Detect which one to use; If the detection or
        # decoding fails, fall back to `self.text` (using chardet to make
        # a best guess).
        encoding = guess_json_utf(self.content)
        if encoding is not None:
            try:
                return complexjson.loads(
                    self.content.decode(encoding), **kwargs
                )
            except UnicodeDecodeError:
                # Wrong UTF codec detected; usually because it's not UTF-8
                # but some other 8-bit codec.  This is an RFC violation,
                # and the server didn't bother to tell us what codec *was*
                # used.
                pass
    return complexjson.loads(self.text, **kwargs)

其中,complexjson是标准json库或simplejson (如果已安装)。

了解了这一点,您实际上可以将关键字参数传递给.json(),它将直接转到json.loads()。这意味着你可以按照answer you linked的建议去做:

代码语言:javascript
复制
from collections import OrderedDict
r.json(object_pairs_hook=OrderedDict)

object_pairs_hook是一个可选的函数,它将通过使用有序的对列表解码的任何对象字面量的结果来调用。将使用object_pairs_hook的返回值,而不使用dict。此功能可用于实现自定义解码器。如果还定义了object_hook,则object_pairs_hook优先。

object_pairs_hook是一个可选函数,它将根据任何具有有序对列表的对象文字解码的结果进行调用。将使用object_pairs_hook的返回值,而不使用dict。此功能可用于实现自定义解码器,这些解码器依赖于keyvalue对的解码顺序(例如,collections.OrderedDict将记住插入的顺序)。如果还定义了object_hook,则object_pairs_hook优先。

因此,无论采用哪种方法,都可以向r.json()提供object_pairs_hook关键字参数。

根据我从评论中收到的信息,您甚至不需要解析json,只需执行以下操作:

代码语言:javascript
复制
text = r.content.decode(requests.utils.guess_json_utf(r.content)).encode('utf-8')

你可以“发布”文本到任何你想要的地方。

票数 2
EN

Stack Overflow用户

发布于 2018-07-19 07:49:49

依赖于服务器(尤其是您无法控制的服务器)的json密钥的顺序是非常脆弱的。The RFC says

对象是零个或多个名称/值对的无序集合,其中名称是字符串,值是字符串、数字、布尔值、null、对象或数组。

它还特别评论:

已经观察到,

JSON解析库在是否使对象成员的顺序对调用软件可见这一点上存在差异。行为不依赖于成员顺序的实现将是可互操作的,因为它们不会受到这些差异的影响。

因此,对于一个实现(在服务器上)来说,改变它对生成的JSON的排序方式是符合RFC的。

如果您不知道服务器是否使用了保证顺序的序列化库,那么这在将来可能会中断(如果该库发生了变化)。即使您这样做了,如果该库使用服务器语言的等价物dict,升级语言或标准库可能会更改该dict的语义,从而导致顺序更改(以及代码中断)。例如,从Python3.6到3.7,dicts从任意顺序更改为按插入排序。在其他语言中,例如rust,它们将散列映射使用的散列函数植入prevent DoS attacks,排序可能取决于用于散列函数种子的随机性(在运行时决定,如果您重新启动服务器,则可能会有所不同)。

如果您知道您需要以特定的顺序构建数据,则会更加安全:

代码语言:javascript
复制
from collections import OrderedDict

ORDERED_KEYS = ['first', 'second', 'third']
ordered_json = OrderedDict((k, r.json()[k]) for k in ORDERED_KEYS)

从您的评论来看,您似乎需要再次序列化该字典。如果在OrderedDict上使用json.dumps,序列化将按插入顺序进行:

代码语言:javascript
复制
import json

serialized_ordered_json = json.dumps(ordered_json)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51412225

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档