繁体   English   中英

将二维列表写入JSON文件

[英]Write two-dimensional list to JSON file

我有一个二维列表,如:

data = [[1,2,3], [2,3,4], [4,5,6]]

我想把它写成JSON文件,如下所示:

{
    'data':[
        [1,2,3],
        [2,3,4],
        [4,5,6]
    ]
}

我得到这个: json.dumps(data, indent=4, sort_keys=True)

{
    'data':[
        [
         1,
         2,
         3
        ],
        [
         2,
         3,
         4
        ],
        [
         4,
         5,
         6]
    ]
}

这是另一个问题如何在使用JSON模块进行漂亮打印时实现自定义缩进? ,但那是字典。

我以为你可以用对另一个类似问题的答案做你想做的事。 虽然它适用于json.dumps() ,但你指出它不是出于某种原因使用json.dump()

在研究了这个问题之后,我发现在链接的答案中被覆盖的派生json.JSONEncoderencode()方法仅在调用json.JSONEncoder dumps()调用,而不是在调用dump()调用。

幸运的是,我很快就能够确定iterencode()方法不会被调用在这两种情况下,所以能够通过更多或更少的只是移动从代码简单地解决这个问题encode()并把它变成这个其他方法来代替。

下面的代码是修订版本,其中包含以下更改:

在我对其他问题的回答中修改了代码版本:

from _ctypes import PyObj_FromPtr  # see https://stackoverflow.com/a/15012814/355230
import json
import re


class NoIndent(object):
    """ Value wrapper. """
    def __init__(self, value):
        if not isinstance(value, (list, tuple)):
            raise TypeError('Only lists and tuples can be wrapped')
        self.value = value


class MyEncoder(json.JSONEncoder):
    FORMAT_SPEC = '@@{}@@'  # Unique string pattern of NoIndent object ids.
    regex = re.compile(FORMAT_SPEC.format(r'(\d+)'))  # compile(r'@@(\d+)@@')

    def __init__(self, **kwargs):
        # Keyword arguments to ignore when encoding NoIndent wrapped values.
        ignore = {'cls', 'indent'}

        # Save copy of any keyword argument values needed for use here.
        self._kwargs = {k: v for k, v in kwargs.items() if k not in ignore}
        super(MyEncoder, self).__init__(**kwargs)

    def default(self, obj):
        return (self.FORMAT_SPEC.format(id(obj)) if isinstance(obj, NoIndent)
                    else super(MyEncoder, self).default(obj))

    def iterencode(self, obj, **kwargs):
        format_spec = self.FORMAT_SPEC  # Local var to expedite access.

        # Replace any marked-up NoIndent wrapped values in the JSON repr
        # with the json.dumps() of the corresponding wrapped Python object.
        for encoded in super(MyEncoder, self).iterencode(obj, **kwargs):
            match = self.regex.search(encoded)
            if match:
                id = int(match.group(1))
                no_indent = PyObj_FromPtr(id)
                json_repr = json.dumps(no_indent.value, **self._kwargs)
                # Replace the matched id string with json formatted representation
                # of the corresponding Python object.
                encoded = encoded.replace(
                            '"{}"'.format(format_spec.format(id)), json_repr)

            yield encoded

将它应用于您的问题:

# Example of using it to do get the results you want.

alfa = [('a','b','c'), ('d','e','f'), ('g','h','i')]
data = [(1,2,3), (2,3,4), (4,5,6)]

data_struct = {
    'data': [NoIndent(elem) for elem in data],
    'alfa': [NoIndent(elem) for elem in alfa],
}

print(json.dumps(data_struct, cls=MyEncoder, sort_keys=True, indent=4))

# test custom JSONEncoder with json.dump()
with open('data_struct.json', 'w') as fp:
    json.dump(data_struct, fp, cls=MyEncoder, sort_keys=True, indent=4)
    fp.write('\n')  # Add a newline to very end (optional).

显示的输出(以及data_struct.json文件的结果内容):

{
    "alfa": [
        ["a", "b", "c"],
        ["d", "e", "f"],
        ["g", "h", "i"]
    ],
    "data": [
        [1, 2, 3],
        [2, 3, 4],
        [4, 5, 6]
    ]
}

您只需将其添加到空dict中:

data = [[1,2,3], [2,3,4], [4,5,6]]
a = {}
a.update({"data":data})
print a

#{'data': [[1, 2, 3], [2, 3, 4], [4, 5, 6]]}

你在第一种风格中尝试的只是一种dict格式。 从该字典中获取精确的json您可以将此dict添加到json.dump以转储该文件。

对于json格式,您只需将其转储为:

import json
b = json.dumps(a)
print b
#{"data": [[1, 2, 3], [2, 3, 4], [4, 5, 6]]}

您可以访问pro.jsonlint.com并检查json格式是否正确。

暂无
暂无

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

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