在不知道数据布局的情况下访问json类型的数据?

时间:2013-02-21 22:32:05

标签: python json list dictionary

我有一个带有JSON数据的文件,我正在使用json.load加载。 假设我想在json数据中放入一个变量,该数据引用另一个数据字段。如何在python中处理这个引用?

eg:

{
  "dictionary" : {
    "list_1" : [
      "item_1"
    ],

    "list_2" : [
      "$dictionary.list_1"
    ]
  }
}

当我遇到$时,我希望list_2从以下位置获取数据:dictionary.list_1 并扩展list_2,就像我用我的python代码编写的那样:

jsonData["dictionary"]["list_2"].extend(jsonData["dictionary"]["list_1"])

1 个答案:

答案 0 :(得分:1)

据我所知,JSON标准中没有任何内容可用于引用。我的第一个建议是使用YAML,其Node Anchors形式的引用。 Python有一个很好的YAML实现,它支持那些。

话虽如此,如果你开始使用JSON,你将不得不推出自己的实现。

一个可能的例子(虽然这不会通过引用的数组扩展当前数组,因为在dicts的情况下它是不明确的,它用它所引用的值替换引用)在下面。请注意,它不会处理格式错误的引用,您必须自己添加错误检查或保证没有格式错误的引用。如果您想将其更改为扩展而不是替换,您可以,但是您比我更了解您的用例,因此您将能够以这种方式指定它。这是为了给你一个起点。

def resolve_references(structure, sub_structure=None):
    if sub_structure is None:
        return resolve_references(structure, structure)
    if isinstance(sub_structure, list):
        tmp = []
        for item in sub_structure:
            tmp.append(resolve_references(structure, item))
        return tmp

    if isinstance(sub_structure, dict):
        tmp = {}
        for key,value in sub_structure.items():
            tmp[key] = resolve_references(structure, value)
        return tmp

    if isinstance(sub_structure, str) or isinstance(sub_structure, unicode):
        if sub_structure[0] != "$":
            return sub_structure

        keys = sub_structure[1:].split(".")
        def get_value(obj, key):
            if isinstance(obj, dict):
                return obj[key]
            if isinstance(obj, list):
                return obj[int(key)]
            return value

        value = get_value(structure, keys[0])
        for key in keys[1:]:
            value = get_value(value, key)
        return value
    return sub_structure

使用示例:

>>> import json
>>> json_str = """
... {
...   "dictionary" : {
...     "list_1" : [
...       "item_1"
...     ],
... 
...     "list_2" : "$dictionary.list_1"
...   }
... }
... """
>>> obj = json.loads(json_str)
>>> resolve_references(obj)
{u'dictionary': {u'list_2': [u'item_1'], u'list_1': [u'item_1']}}