Python 中的 TreeView 到 JSON

TreeView to JSON in Python

[编辑:显然这个文件看起来类似于 h5 格式] 我正在尝试使用 Python 中的 hyperspy 从扩展名为 (.dm3) 的文件中提取元数据,我能够获取所有数据,但它被保存在树视图中,但我需要 [=26] 中的数据=] 我尝试制作自己的解析器来转换它,这在大多数情况下都有效,但后来失败了:

TreeView data generated

有没有我可以用来在 pyhton 中将树视图转换为 JSON 的库或包?

我的解析器:

def writearray(file,string):
    k = string.split('=')
    file.write('"' + k[0] + '":' + '[')
    for char in k[1]:
        file.write(char)
    file.write(']')

def writenum(file,string):
    k = string.split('=')
    file.write('"' + k[0] + '":' + k[1])

def writestr(file,string):
    k = string.split('=')
    file.write('"' + k[0] + '":' +'"'+ k[1]+'"')

def startnew(file,string):
    file.write('"'+string+'":'+'{\n')

def closenum(file,string):
    k = string.split('=')
    file.write('"' + k[0] + '":' + k[1] + '\n')
    file.write('},\n')

def closestr(file,string):
    k = string.split('=')
    file.write('"' + k[0] + '":' + '"' + k[1] + '"' + '\n')
    file.write('},\n')

def closearr(file,string):
    k = string.split('=')
    file.write('"' + k[0] + '":' + '[')
    for char in k[1]:
        file.write(char)
    file.write(']\n')
    file.write('},\n')

def strfix(string):
    temp = ''
    for char in string:
        if char != ' ':
            temp += char
    return temp

def writethis(file,string):
    stripped = strfix(string)
    if "=" in stripped:
        temp = stripped.split("=")
        if ',' in temp[1]:
            writearray(file,stripped)
        elif temp[1].isdigit() or temp[1].isdecimal():
            writenum(file,stripped)
        else:
            writestr(file,stripped)

def createMetaData(dm3file):
    txtfile = os.path.splitext(dm3file)[0] + '.txt'
    jsonfile = os.path.splitext(dm3file)[0] + '.json'
    s = hs.load(dm3file)
    s.original_metadata.export(txtfile)
    file1 = open(txtfile, 'r', encoding="utf-8")
    Lines = file1.readlines()
    k = []
    for line in Lines:
        k.append(line)
    L = []
    for string in k:
        temp = ''
        for char in string:
            if char.isalpha() or char.isdigit() or char == '=' or char == ' ' or char == '<' or char == '>' or char == ',' or char == '.' or char == '-' or char == ':':
                temp += char
        L.append(temp)
    file2 = open(jsonfile, 'w', encoding="utf-8")
    file2.write('{\n')
    for i in range(0, len(L) - 1):
        currentspaces = len(L[i]) - len(L[i].lstrip())
        nextspaces = len(L[i + 1]) - len(L[i + 1].lstrip())
        sub = nextspaces - currentspaces
        if i != len(L) - 2:
            if (sub == 0):
                writethis(file2, L[i])
                if '=' in L[i]:
                    file2.write(',\n')
                else:
                    file2.write('\n')
            elif sub > 0:
                startnew(file2, L[i])
            else:
                if sub == -3:
                    writethis(file2, L[i])
                    file2.write('\n},\n')
                elif sub == -7:
                    writethis(file2, L[i])
                    file2.write('\n}\n},\n')
        else:
            writethis(file2, L[i])
            file2.write('\n}\n}\n}\n}')
    file1.close()
    os.remove(txtfile)
enter code here

我为树视图格式编写了一个解析器:

from ast import literal_eval
from collections import abc
from more_itertools import peekable


def parse_literal(x: str):
    try:
        return literal_eval(x)
    except Exception:
        return x.strip()


def _treeview_parse_list(lines: peekable) -> list:
    list_as_dict = {}
    for line in (x.strip() for x in lines):
        raw_k, raw_v = line.split(' = ')
        list_as_dict[int(raw_k.split()[-1][1:-1])] = parse_literal(raw_v)
        peek = lines.peek(None)
        if '╚' in line or (peek is not None and '├' in peek):
            break
    list_as_list = [None] * (max(list_as_dict) + 1)
    for idx, v in list_as_dict.items():
        list_as_list[idx] = v
    return list_as_list


def _treeview_parse_dict(lines: peekable) -> dict:
    node = {}
    for line in (x.strip() for x in lines):
        if ' = ' in line:
            raw_k, raw_v = line.split(' = ')
            node[raw_k.split()[-1]] = parse_literal(raw_v)
        elif '<list>' in line:
            node[line.split()[-2]] = _treeview_parse_list(lines)
        else:
            try:
                idx = line.index('├')
            except ValueError:
                idx = line.index('└')
            peek = lines.peek(None)
            if peek is not None and '├' in peek and idx == peek.index('├'):
                node[line.split()[-1]] = {}
            else:
                node[line.split()[-1]] = _treeview_parse_dict(lines)
        if '└' in line:
            break
    return node


def treeview_to_dict(lines: abc.Iterable) -> dict:
    return _treeview_parse_dict(peekable(lines))

用法:

with open('meta.txt') as f:
    d = treeview_to_dict(f)

您可以使用 Python 的内置 json 库将元数据作为 JSON 文件获取:

import json

with open('meta.txt') as txt_file:
    with open('meta.json', 'w') as json_file:
        json.dump(treeview_to_dict(txt_file), json_file, indent=4)

我添加了 indent=4 以使 JSON 文件更易于阅读,以便您可以根据原始格式验证它。据我所知,它们以合理的方式匹配。

在我写这篇文章时,它使用了第三方 more_itertools.peekable class。如果你不能使用more_itertools,那么你自己实现那个功能应该不会太难,或者只是重构代码,这样就不需要再往前看了。


License:

这是在 public 域中发布的免费且不受限制的软件。

任何人都可以自由复制、修改、发布、使用、编译、出售或 以源代码形式或编译后的形式分发此软件 二进制,用于任何目的,商业或非商业,以及任何 意思是.

在承认版权法的司法管辖区内,本软件的作者或作者将本软件的任何和所有版权权益归于 public 域。我们作出这种奉献是为了 public 的整体利益,而不利于我们的继承人和 继任者。我们希望这种奉献成为一种公开的行为 永久放弃所有现在和未来的权利 受版权法保护的软件。

软件按“原样”提供,不提供任何形式的保证, 明示或暗示的,包括但不限于 适销性、特定用途的适用性和侵权。在任何情况下,作者均不对任何索赔、损害或其他责任负责,无论是在合同诉讼、侵权行为还是其他方面,由软件或软件的使用或其他交易引起、由软件引起或与之相关。

详情请参考https://unlicense.org