2012-06-14 65 views
1

我需要將分層數據(AVRO數據,歸結爲JSON)轉換爲表格數據(csv)。由於AVRO具有嚴格的模式,我基本知道JSON將採取何種形式,但我必須爲許多不同的模式執行此操作,所以我正在尋求一種一致的聲明方式來表達我需要做出的轉換。例如,如果我輸入的數據看起來像這樣...尋找將JSON轉換爲CSV的DSL

{ 
    "customers": [ 
     { 
      "addresses": [ 
       { 
        "city": "Los Angeles", 
        "country": "USA", 
        "county": null, 
        "postalCode": "90064", 
        "stateOrProvince": "California", 
        "street1": "11832 W. Pico Blvd.", 
        "street2": "", 
        "street3": "", 
        "street4": "", 
        "tags": [ 
         "BILLING" 
        ] 
       } 
      ], 
      "company": "", 
      "dateCreated": "2009-04-24T11:42:31+00:00", 
      "dateOfBirth": null, 
      "doNotCall": null, 
      "email": { 
       "emailAddress": "[email protected]" 
      }, 
      "emailOptOut": null, 
      "fullName": { 
       "firstName": "Test", 
       "lastName": "General", 
       "middleName": "", 
       "prefix": "", 
       "suffix": "" 
      }, 
      "gender": null, 
      "id": { 
       "Id": "2", 
       "namespace": "1000020016" 
      }, 
      "lastModified": "2009-05-08T23:33:06+00:00", 
      "primaryPhone": { 
       "number": "866.4.VARIEN", 
       "type": "UNKNOWN" 
      }, 
      "sourceIds": null 
     } 
    ], 
    "totalItemsFound": 3 
} 

...我可能需要輸出一行對每一個客戶,是這樣的:

MERCHANT ID|NUM CUSTOMERS|ID|FIRST NAME|LAST NAME|EMAIL|PHONE|STREET|CITY|STATE|ZIP|COUNTRY|EMAIL PREFERENCE 
some.merch|3|1000020016-2|Test|General|[email protected]|866.4.VARIEN|11832 W. Pico Blvd.|Los Angeles|California|90064|USA|N 

我需要能夠表達下面的東西:所有日期-的出生

  • 回覆:

    1. 從給定的鍵作爲數組獲取所有的值泥炭一個值在每一行:totalItemsFound,每一行中重複
    2. 重複每一個來自靜態數據行中的靜態值,我已經知道商家通道不會改變
    3. 而棘手的一個:任意操縱輸入數據,以產生所需的輸出:
      • 轉換客戶的ID到名字空間-ID
      • 反轉並改變空/布爾值到Y/N,如在emailOptOut到電子郵件偏好
      • (重新)格式化日期或貨幣

    我開始了jsonpath,但這隻解決了#1以上。我一直在慢慢增加一個圍繞jsonpath的語言來服務於2和3,但我對4的真正答案並不是很好(除了eval,我真的很討厭這麼做)。我看着JSON/T,但找不到它的Python庫。我甚至認真考慮編寫一箇中間件來將JSON轉換爲XML,以便我可以使用XSLT,但是我希望S/O中的某人在我得到絕望之前有更好的解決方案。

  • 回答

    1

    爲什麼不嘗試進行功能分解不象什麼如下:

    w = csv.writer(...) 
    for r in records: 
        l = {} 
        for field in fields: 
         f_ = rename(field) 
         v_ = transform(field, r.get(field, default(field))) 
         l[f_] = v_ 
        w.write(l) 
    

    其中rename舊的字段名稱映射到換新的,transform根據變換的字段設置轉換字段的值,並default返回要分配給此字段的值。

    因此,您只需要定義字段列表和功能:rename,transformdefault

    對於你給出的例子:

    def rename(field): 
        t = {'emailOptOut':'EMAIL PREFERENCE'} 
        return t.get(field, field) 
    
    def transform(field, data): 
        t = {'emailOptOut': bool} 
        return t.get(field, lambda a: a)(data) 
    
    def default(field) 
        t = {'MERCHANT ID':11039215} 
        return t.get(field, None) 
    
    +0

    謝謝,我得想想這個答案。不幸的是,對於我平常的S/O工作流程來說,這個問題不是我可以只看一個答案,而是決定它是正確的。 :) – kojiro