简体   繁体   English

python中对Json的点表示法

[英]Dot notation to Json in python

I receive data from the Loggly service in dot notation, but to put data back in, it must be in JSON. 我从Loggly服务以点表示法接收数据,但要放回数据,它必须为JSON。

Hence, I need to convert: 因此,我需要转换:

{'json.message.status.time':50, 'json.message.code.response':80, 'json.time':100}

Into: 进入:

{'message': {'code': {'response': 80}, 'status': {'time': 50}}, 'time': 100}

I have put together a function to do so, but I wonder if there is a more direct and simpler way to accomplish the same result. 我已经组合了一个函数来执行此操作,但是我想知道是否有更直接,更简单的方法来实现相同的结果。

def dot_to_json(a):

    # Create root for JSON tree structure
    resp = {}

    for k,v in a.items():
        # eliminate json. (if metric comes from another type, it will keep its root)
        k = re.sub(r'\bjson.\b','',k)
        if '.' in k:
            # Field has a dot
            r = resp
            s = ''
            k2 =  k.split('.')
            l = len(k2)
            count = 0
            t = {}
            for f in k2:
                count += 1
                if f not in resp.keys():
                    r[f]={}
                r = r[f]
                if count < l:
                    s += "['" + f + "']"
                else:
                    s = "resp%s" % s
                    t = eval(s)
                    # Assign value to the last branch
                    t[f] = v
        else:
            r2 = resp
            if k not in resp.keys():
                r2[k] = {}
            r2[k] = v
    return resp

You can turn the path into dictionary access with: 您可以使用以下方法将路径转换为字典访问权限:

def dot_to_json(a):
    output = {}
    for key, value in a.iteritems():
        path = key.split('.')
        if path[0] == 'json':
            path = path[1:]
        target = reduce(lambda d, k: d.setdefault(k, {}), path[:-1], output)
        target[path[-1]] = value
    return output

This takes the key as a path, ignoring the first json part. 这将密钥作为路径,而忽略了第一个json部分。 With reduce() you can walk the elements of path (except for the last one) and fetch the nested dictionary with it. 使用reduce()您可以遍历path的元素(最后一个除外),并使用它来获取嵌套字典。

Essentially you start at output and for each element in path fetch the value and use that value as the input for the next iteration. 本质上,您从output开始,并为path每个元素获取值,并将该值用作下一次迭代的输入。 Here dict.setdefault() is used to default to a new empty dictionary each time a key doesn't yet exist. 在这里, dict.setdefault()用于在每次键都不存在时默认使用一个新的空字典。 For a path ['foo', 'bar', 'baz'] this comes down to the call output.setdefault('foo', {}).setdefault('bar', {}).setdefault('baz', {}) , only more compact and supporting arbitrary length paths. 对于路径['foo', 'bar', 'baz']output.setdefault('foo', {}).setdefault('bar', {}).setdefault('baz', {})调用output.setdefault('foo', {}).setdefault('bar', {}).setdefault('baz', {}) ,只有更紧凑且支持任意长度的路径。

The innermost dictionary is then used to set the value with the last element of the path as the key. 然后,使用最里面的字典以路径的最后一个元素为键来设置值。

Demo: 演示:

>>> def dot_to_json(a):
...     output = {}
...     for key, value in a.iteritems():
...         path = key.split('.')[1:]  # ignore the json. prefix
...         target = reduce(lambda d, k: d.setdefault(k, {}), path[:-1], output)
...         target[path[-1]] = value
...     return output
... 
>>> dot_to_json({'json.message.status.time':50, 'json.message.code.response':80, 'json.time':100}))
{'message': {'status': {'time': 50}, 'code': {'response': 80}}, 'time': 100}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM