对于模糊的标题感到抱歉,我需要一些Python魔法的帮助,并且无法想到任何更具描述性的内容。
我有一个固定的JSON数据结构,我需要将CSV文件转换为。结构是固定的,但与列表等深深嵌套。它与此类似,但更复杂:
{
"foo" : bar,
"baz" : qux,
"nub" : [
{
"bub": "gob",
"nab": [
{
"nip": "jus",
"the": "tip",
},
...
],
},
...
],
"cok": "hed"
}
希望你明白了。列出列表上的列表等等。我的csv可能看起来像这样:
foo, baz, nub.bub, nub.nab.nip, nub.nab.the, cok
bar, qux, "gob" ,,,, "hed"
,,,,, "nab", "jus","tip",,
,,,,, "nab", "other", "values",,
很抱歉,如果这很难阅读,但基本的想法是,如果列出的项目将在下一行,并重复值以表示哪些子列表属于什么。
我不是在寻找任何人来解决这个烂摊子的问题,也许是关于技术或事情的一些指示。
现在我有一个粗略的计划:
我首先将标题转换为包含键的元组列表。对于每组行(项目),我将创建我的模板dict的副本。我有一个函数,它将从一个键元组设置一个dict值,除非它找到一个列表。在这种情况下,我将调用一个时髦的递归函数并将其传递给我的迭代器,并继续填充该函数中的dict,并在找到新列表时进行递归调用。
我也可以做很多硬编码,但那有什么好玩的呢?
这就是我的故事。再次,只是寻找一些关于最佳方法的指针。我写的很快,所以可能有点令人困惑,如果有任何更多的信息会有所帮助,请告诉我。谢谢!
答案 0 :(得分:1)
您的JSON格式不正确。此外,您的json必须不包含数组才能达到您想要的效果。
def _tocsv(obj, base=''):
flat_dict = {}
for k in obj:
value = obj[k]
if isinstance(value, dict):
flat_dict.update(_tocsv(value, base + k + '.'))
elif isinstance(value, (int, long, str, unicode, float, bool)):
flat_dict[base + k] = value
else:
raise ValueError("Can't serialize value of type "+ type(value).__name__)
return flat_dict
def tocsv(json_content):
#assume you imported json
value = json.loads(json_content)
if isinstance(value, dict):
return _tocsv(value)
else:
raise ValueError("JSON root object must be a hash")
会让你扁平化:
{
foo: "nestor",
bar: "kirchner",
baz: {
clorch: 1,
narf: 2,
peep: {
ooo: "you suck"
}
}
}
成像:
{"foo": "nestor", "bar": "kirchner", "baz.clorch": 1, "baz.narf": 2, "baz.peep.ooo": "you suck"}
密钥不保留任何特定订单。如果要保留顺序,可以将flat_dict = {}
替换为OrderedDict的构造。
假设您有一系列这样平坦的词组:
def tocsv_many(json_str):
#assume you imported json
value = json.loads(json_content)
result = []
if isinstance(value, list):
for element in value:
if isinstance(element, dict):
result.append(_tocsv(element))
else:
raise ValueError("root children must be dicts")
else:
raise ValueError("The JSON root must be a list")
flat_dicts = tocsv_many(yourJsonInput)
你可以:
csvlines = []
列表,其中包含ur文件的csv行。keysSet = set()
,其中包含可能的键。对于您拥有的每个dict,将.keys()添加到集合中。正常设置不保证密钥顺序;使用排序集代替。最后我们得到第一个CSV行。
for flat_dict in flat_dicts:
keysSet.extend(flat_dict.keys())
csvlines.appens(",".join(keysSet))
对于你拥有的每个dict(再次迭代),你生成一个这样的数组:
for flat_dict in flat_dicts:
csvline = ",".join([json.dumps(flat_dict.get(keyInSet, '')) for keyInSet in keysSet])
csvlines.append(csvline)
voilah!你有csvlines