我有一个二维列表,如:
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):
json.dumps(data, indent=4, sort_keys=True)
{ 'data':[ [ 1, 2, 3 ], [ 2, 3, 4 ], [ 4, 5, 6] ] }
我认为您可以使用我对另一个类似问题的答案来做您想要的事情。当与之搭配使用时json.dumps(),您指出并非由于某种原因json.dump()。
json.dumps()
json.dump()
在调查此事之后,我发现在链接的答案中被覆盖encode()的派生方法json.JSONEncoder仅在dumps()被调用时才被调用,而在何时dump()被调用时才被调用。
encode()
json.JSONEncoder
dumps()
dump()
幸运的是,我很快就能够确定在两种情况下都 确实 调用了该iterencode()方法,因此能够通过或多或少地只是将代码移至另一个方法中而解决该问题。 __encode()
iterencode()
紧接在下面的代码是修订版,其中有此更改:
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] ] }