2014-07-02 85 views
0

对于模糊标题感到抱歉,我需要一些关于Python魔法的帮助,并且想不到任何更具描述性的内容。Python脚本将复杂的扁平化数据转换为JSON

我有一个固定的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,并在发现新列表时进行递归调用。

我也可以做很多硬编码,但是有什么好玩的呢?

这就是我的故事。再次,只是寻找一些关于如何做到这一点的最佳方法的指针。我写得很快,所以它可能有点混乱,请让我知道,如果有更多的信息会有所帮助。谢谢!

+0

有问题的格式基本上是不同的,试图解析一个到另一个将证明两个问题,并容易出错。 _为什么你需要这样的csv文件? –

+0

有人为我制作测试数据集,这是他们使用的格式。这并不理想,但我不想让他们改变它(他们正在用手做这件事......)。我可以解析它,这只会是一个痛苦的屁股。 – user3779812

回答

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

密钥不保存任何特定的顺序。如果你想保持秩序,你可以用0123代替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) 

,你可以:

  1. 创建csvlines = []名单将举行乌拉圭回合文件中的CSV行。
  2. 创建一个keysSet = set()它将保存可能的密钥。
  3. 对于您以这种方式获得的每个字典,请将.keys()添加到集合中。没有按键顺序保证正常设置;改为使用有序集。最后我们得到第一个CSV行。

    for flat_dict in flat_dicts: 
        keysSet.extend(flat_dict.keys()) 
    csvlines.appens(",".join(keysSet)) 
    
  4. 每个字典你已经(再次循环),您生成一个这样的数组:

    for flat_dict in flat_dicts: 
        csvline = ",".join([json.dumps(flat_dict.get(keyInSet, '')) for keyInSet in keysSet]) 
        csvlines.append(csvline) 
    
  5. voilah!你有你的线csvlines

+0

感谢您的回答!不幸的是,我要从csv开始。我无法控制任何一种数据格式,这正是我必须使用的。我可能只是要硬编码很多东西来挽救我自己的头痛。 – user3779812

+0

如果你来自csv,它更容易。存储第一行并用逗号将它们分解为键。对于后面的每一行:用逗号分隔它,用键()将它分开,迭代并通过迭代创建一个json结构(并通过按点分隔键) –