【问题标题】:In place editing of Python dictionary or parsing json to object就地编辑 Python 字典或将 json 解析为对象
【发布时间】:2013-04-16 14:53:54
【问题描述】:

我绝不是 Python 大师,但我知道自己的方式。然而,在过去的两个小时里,我一直在抨击以下内容:

我正在使用 json.loads() 函数解析来自 WCF Web 服务的 JSON 响应。结果是我在整个应用程序中使用的 Python 字典。但是,我现在需要混淆 id、reseller_id 等以便在 HTTP GET 请求中使用。

这是一个响应的一个示例:(注意,我有很多这样的响应,所以我正在寻找一个通用的解决方案。)我想要用 id 值的哈希替换任何 id 的值

{
    "token":"String content",
    "user":{
        "distributor":{
            "email":"String content",
            "id":2147483647,
            "name":"String content"
        },
        "email":"String content",
        "first_name":"String content",
        "id":2147483647,
        "last_name":"String content",
        "reseller":{
            "email":"String content",
            "id":2147483647,
            "name":"String content",
            "portal_css":"String content",
            "portal_logo":"String content",
            "portal_name":"String content",
            "portal_url":"String content"
        },
        "role":2147483647
    }
}

我尝试过各种策略,使用如下代码:

result = json.loads(json_result, object_hook=lambda d: namedtuple('X', d.keys())(*d.values()))

def fun(d):
    if 'id' in d:
        yield d['id']
    for k in d:
        if isinstance(d[k], list):
            for i in d[k]:
                for j in fun(i):
                    yield j

我无法让它正常工作。所以:

问题 1: 我可以将 json 转换为(匿名)Python 对象吗?

问题 2: 我可以就地编辑结果字典吗?

问题 3: 当一切都失败了;有人知道如何实现这一目标吗?

非常感谢!

【问题讨论】:

  • json.loads(json_result) 给你一本字典。 “匿名 Python 对象”是什么意思?你能举一个你想要的输出的例子吗? (我认为您想对 ID 进行哈希处理,但我没有看到任何尝试在您的代码示例中对任何内容进行哈希处理)。你想要什么样的散列?
  • 澄清一下,您提到的“HTTP GET 请求”是否需要传递整个字典,还是只传递散列 ID?
  • @Aya,只是散列的 id,例如 /reseller/28763298728/Reseller-A/users 而不是 /reseller/1/users
  • TBH,你也可以让dict保持原样,在需要的时候按需计算hash。
  • @Berdus JavaScript?你根本没有在问题中提到这一点。也许您在问题中包含了这一点。

标签: python json dictionary


【解决方案1】:
json.loads(data)

解析 json 字符串 data 并返回一个 Python dict,我猜你可以称之为匿名,直到你将它分配给一个变量:

d = json.loads(data)

然后您可以就地修改字典。假设您的所有响应都具有相同的结构,您可以对 id 进行哈希处理,如下所示:

d["user"]["id"] = your_hash_function(d["user"]["id"])

【讨论】:

  • 是吗?我试过这个,但没有令人满意的结果。我会再试一次。我仍在寻找更通用的方法,但如果可行,我很乐意在我的“WCFBackend”类函数中使用您的方法。
  • @Berdus 你的问题到底出在哪里?您是否收到错误或某些内容未按预期工作?
  • 我有点不好意思地说 *** result["user"]["id"] = "test" *** 似乎有效。在我的任务中,我必须在我的代码中忽略了一个错误,之后我得出结论认为 dicts 是不可变的。不过,我仍然对更通用的方法感兴趣。但是,您的回答确实符合要求!
  • @Berdus 那么这是给出错误(如果是,是哪个)还是没有产生预期的结果?
【解决方案2】:

这是我快速组合起来的解决方案。它通过您的字典递归并在键为 id 时替换值。这不是最终解决方案,因为它不支持列表,但我确定这是否适合您,您可以从那里获取它吗?

def f(d):
    _dict = {}
    for k, v in d.items():
        if isinstance(v, dict):
            _dict.update({k: f(v)})
        else:
            if k == 'id':
                print 'id found', v
                v = EncryptValueHere(v)
            _dict.update({k:v})

    return _dict

【讨论】:

  • 因为 OP 有兴趣更改值,您不能直接更改原始字典中的值,而不是创建一个新值吗?
  • 那是可能的。毕竟字典是通过引用传递的。将考虑对其进行修改以支持这一点。除非这本词典非常庞大,否则替换整个词典应该不会对性能造成太大影响。
【解决方案3】:

是的。 json.loads 根据实际的 json 对象返回一个 Python 对象。查看conversion table 了解更多详情。无需像在 .Net 中那样寻找特殊的匿名对象。

result = json.loads(json_text)

您可以就地编辑这个result

result['user']['id'] = 'some_new_value' 

在解析 json 时尝试 object_pairs_hook 参数:

def hide_ids(o):
    d = dict(o)
    if 'id' in d:
        d['id'] = '----{}----'.format(d['id'])
    return d

result = json.loads(json_text, object_pairs_hook=hide_ids)

只需使用您喜欢的混淆逻辑进行修改,您就可以开始了。

【讨论】:

  • 看起来很有希望...感谢您的评论,我刚刚接受了 ExP 的回答。为 object_pairs_hook +1。 PS:我当然看过文档。在荷兰,我们有一句话(粗略翻译):“盯着自己瞎”。这可能是我问题的根源。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-04-02
  • 2019-10-22
  • 1970-01-01
  • 1970-01-01
  • 2013-05-12
  • 2015-08-18
  • 1970-01-01
相关资源
最近更新 更多