迭代通过键替换Python中的字符串替换

时间:2014-12-10 22:14:23

标签: python json mongodb yaml pymongo

我正在尝试通过pyMongo将YAML(JSON的各个行)插入到mongoDB中。我的一些密钥包含句点,这会产生错误bson.errors.InvalidDocument: key 'job.no' must not contain '.'。根据{{​​3}},我需要迭代我的键来替换句号,这是有道理的。

我遇到的问题是我的数据很混乱。我的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}

但我没看到这是如何结合在一起的。有人可以帮忙吗?

2 个答案:

答案 0 :(得分:3)

这种递归解决方案怎么样?请注意,由于标准的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}'))

答案 1 :(得分:0)

一个对我有用的麻烦的解决方案(但是您需要跟踪代码中的修改)是简单地包装包含“。”的字典。在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}]