Write two-dimensional list to JSON file

前端 未结 2 2054
别跟我提以往
别跟我提以往 2020-12-12 02:39

I have a two-dimensional list like:

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

I want to write it to JSON file like this:

{
    \'d         


        
相关标签:
2条回答
  • 2020-12-12 02:56

    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().

    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.

    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:

    Modified version of the code in my answer to other question:

    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
    

    Applying it to your question:

    # 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).
    

    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]
        ]
    }
    
    0 讨论(0)
  • 2020-12-12 03:02

    You just need to add it to a empty dict as :

    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]]}
    

    What you are trying in the 1st style is just a dict format. To get exact json from that dict You can add this dict to your json.dump to dump the file.

    For json format you just need to dump it as :

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

    You can go to pro.jsonlint.com and check whether the json format is correct or not.

    0 讨论(0)
提交回复
热议问题