将二维列表写入JSON文件 [英] Write two-dimensional list to JSON file

查看:212
本文介绍了将二维列表写入JSON文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个二维列表,如:

I have a two-dimensional list like:

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

我想像这样将其写入JSON文件:

I want to write it to JSON file like this:

{
    '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模块进行漂亮打印时实现自定义缩进?,但这就是字典.

Here is anther question How to implement custom indentation when pretty-printing with the JSON module?, but that's dictionaries.

推荐答案

我认为您可以将我的答案用于另一个类似的问题做你想做的.当它与json.dumps()一起使用时,您指出了json.dump()并非出于某种原因.

I thought you could use my answer to another similar question to do what you want. While it works with json.dumps(), you pointed out that it doesn't for some reason with json.dump().

调查此事后,我发现仅在调用dumps()时才调用在链接的答案中被覆盖的派生json.JSONEncoderencode()方法,而在调用dump()时不调用.

After looking into the matter, I discovered that the encode() method of the derived json.JSONEncoder that was being overridden in the linked answer is only called when dumps() is called, but not when dump() is called.

幸运的是,我很快就能确定在两种情况下都调用了iterencode()方法 ,因此能够通过或多或少地将代码从<移到encode()并将其放入其他方法中.

Fortunately, I quickly was able to determine the iterencode() method does get invoked in both cases, so was able to fix the problem simply by more-or-less just moving the code from encode() and putting it into this other method instead.

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

The code immediately below is revised version with this change in it:

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文件的结果内容):

Output displayed (and resulting contents of the data_struct.json file):

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

这篇关于将二维列表写入JSON文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆