【问题标题】:Iterating Through Keys for String Replacement in Python在 Python 中遍历键以进行字符串替换
【发布时间】:2019-06-20 22:31:19
【问题描述】:

我正在尝试通过 pyMongo 将 YAML(单独的 JSON 行)插入 mongoDB。我的一些键包含句点,这会产生错误bson.errors.InvalidDocument: key 'job.no' must not contain '.'。根据this SO answer,我需要遍历我的键来替换句点,这是有道理的。

我遇到的问题是我的数据很乱。我的 json 包含多层嵌套对象,我事先不知道包含句点的字符串是什么,或者它在哪里(哪个级别)。这是我的数据的一个小样本。

{"uuid":"94e31-02f59","project":{"name":"oasis","job.no":215493452,"subset":"beta"},"time":1412371841024}

我有一个递归迭代我的 JSON 的函数。我尝试了一些变体,但它要么使我的 JSON 变平(不再有嵌套对象),要么只返回第一个对象。我想保持我输入的结构。

def keyCleaner(line):
    for k, v in line.iteritems():
        if isinstance(v, dict):
            keyCleaner(v)
        else:
            nK = k
            if "." in k:
                nK = k.replace(".", "_")
            return nK, v

这是它当前返回的内容:

(u'uuid', u'94e31-02f59')

我希望它返回的是:

{"uuid":"94e31-02f59","project":{"name":"oasis","job_no":215493452,"subset":"beta"},"time":1412371841024}

但我不知道这是如何结合在一起的。有人可以帮忙吗?

【问题讨论】:

  • 只是一个想法,为什么不将所有内容都转换为字符串,例如json.dumps(),修复句点并将其更改回json json.loads(),只是一个想法。
  • 我也有这个想法。我正在处理数十万行,而且我事先不知道要查找什么字符串。现在它的“job.no”,10 行后它可能是“task.no”或“xx9.ze”。对我来说唯一有意义的是在键中查找句点。

标签: python json mongodb yaml pymongo


【解决方案1】:

这个递归解决方案怎么样?请注意,由于标准 Python 的递归限制,深度嵌套的字典可能无法工作。

#!/usr/bin/env python

# parse initial string
import json

def keyCleaner(d):
    if type(d) is dict:
        for key, value in d.iteritems():
            d[key] = keyCleaner(value)
            if '.' in key:
                d[key.replace('.', '_')] = value
                del(d[key])
        return d
    if type(d) is list:
        return map(keyCleaner, d)
    if type(d) is tuple:
        return tuple(map(keyCleaner, d))
    return d

print keyCleaner(json.loads('{"uuid":"94e31-02f59","project":{"name":"oasis","job.no":215493452,"subset":"beta"},"time":1412371841024}'))

【讨论】:

  • 这比我得到的更接近,但看起来它只返回嵌套数组的最后一个对象。这是输出{u'project': (u'subset', u'beta'), u'uuid': u'94e31-02f59', u'time': 1412371841024L}
  • 添加了更多处理。这个想法是使用递归替换每个可能包含更多对象的复杂对象。它也用于散列对象(但散列时还有更多内容)。
  • 太棒了。谢谢!
【解决方案2】:

一个对我有用的不太混乱的解决方案(但您需要跟踪代码中的修改)是简单地包装包含“。”的字典。在 python 列表中并将列表存储在 mongo 中,而不是存储字典(引发错误)。

new_item_to_store = list(dict_to_store.items())

我在存储域字典时遇到问题,即:

{"facebook.com": 2500,
"google.com" : 750,
"bing.com" : 200}

上面显示了 mongo store key 'job.no' must not contain '.' 中的错误,但这工作正常:

[{"facebook.com": 2500,
"google.com" : 750,
"bing.com" : 200}]

【讨论】:

    猜你喜欢
    • 2019-06-06
    • 1970-01-01
    • 1970-01-01
    • 2019-05-29
    • 2018-07-06
    • 2014-06-25
    • 1970-01-01
    • 1970-01-01
    • 2020-03-21
    相关资源
    最近更新 更多