2011-09-22 21 views
8

Ho bisogno di convertire un file csv in un oggetto JSON gerarchico (preferibilmente usando Python). Ho pensato che lo script che ho (sotto) fa un lavoro corretto di conversione in JSON, ma la libreria JavaScript che sto alimentando i dati JSON su (D3.js) non funziona con esso.Python - converte file csv in JSON

il file CSV si presenta così:

subject,branch,book,chapter,Encode ID,Level 1,Level 2,Level 3,Level 4 
MAT,TRI,CK-12 Trigonometry - Second Edition,Right Triangles and an Introduction to Trigonometry,MAT.TRI.000,Right Triangles and an Introduction to Trigonometry,,, 
MAT,TRI,CK-12 Trigonometry - Second Edition,Right Triangles and an Introduction to Trigonometry,MAT.TRI.004,,The Pythagorean Theorem,, 
MAT,TRI,CK-12 Trigonometry - Second Edition,Right Triangles and an Introduction to Trigonometry,MAT.TRI.005,,,The Pythagorean Theorem, 
MAT,TRI,CK-12 Trigonometry - Second Edition,Right Triangles and an Introduction to Trigonometry,MAT.TRI.006,,,Pythagorean Triples, 
MAT,TRI,CK-12 Trigonometry - Second Edition,Right Triangles and an Introduction to Trigonometry,MAT.TRI.007,,,Converse of the Pythagorean Theorem, 
MAT,TRI,CK-12 Trigonometry - Second Edition,Right Triangles and an Introduction to Trigonometry,MAT.TRI.008,,,The Distance Formula, 
MAT,TRI,CK-12 Trigonometry - Second Edition,Right Triangles and an Introduction to Trigonometry,MAT.TRI.009,,Special Right Triangles,, 

In questo momento, ho il seguente codice le generazioni ricorsivamente l'array gerarchica:

import csv 
import json 
import random 

random.seed() 

# open up the csv file 
f = open('/path/to/file','rU') 
c = csv.DictReader(f) 

# lists for keeping track of what subjects and branches I've already iterated over 
subject_list = [] 
branch_list = [] 
lev1_list = [] 
lev2_list = [] 
lev3_list = [] 
lev4_list = [] 

# iterate through file 
i = 0 
for row in c: 
    if i == 0: 
     subject = row['subject'] 
     branch = row['branch'] 
     if len(row['Level 1']) > 0: 
      lev1 = row['Level 1'] 
     else: 
      lev2 = None 
     if len(row['Level 2']) > 0: 
      lev2 = row['Level 2'] 
     else: 
      lev2 = None 
     if len(row['Level 3']) > 0: 
      lev3 = row['Level 3'] 
     else: 
      lev3 = None 

    else: 
     if row['subject'] != subject: 

      # add all branches to this subject 
      subject_list.append({'name':subject,'type':'subject','children':branch_list}) 


      # set current subject 
      subject = row['subject'] 

     if row['branch'] != branch: 
      # add all concepts to this branch 
      branch_list.append({'name':branch,'type':'branch','children':lev1_list}) 

      # empty lev1_list 
      lev1_list = [] 

      # set new branch 
      branch = row['branch'] 

     if len(row['Level 1']) > 0 and row['Level 1'] != lev1: 
      # print lev1 
      # add all level 2 concepts to this level 1 
      lev1_list.append({'name':lev1,'type':'concept','level':1,'children':lev2_list}) 
      #print lev1 
      #empty lev2_list 
      lev2_list = [] 

      #lev1_list.append(row['Level 1']) 
      lev1 = row['Level 1'] 

     if len(row['Level 2']) > 0 and row['Level 2'] != lev3: 
      #print lev2 
      #print lev3_list 
      # add all level 3 concepts to this level 2 
      if lev2 is not None: 
       lev2_list.append({'name':lev2,'type':'concept','level':2,'children':lev3_list}) 

      # empty lev3_list 
      lev3_list = [] 

      # lev2_list.append(row['Level 2']) 
      lev2 = row['Level 2'] 

     if len(row['Level 3']) > 0 and row['Level 3'] != lev3: 
      # print lev3 
      # add all level 4 concepts to this level 4 
      # lev3_list.append({'name':lev3,'type':'concept','level':3}) 

      # empty level 4 concepts 
      # lev4_list = [] 

      # add new level 3 
      if lev3 is not None: 
       lev3_list.append({'name':lev3,'type':'concept','level':3,'size':random.randint(1,100)}) 
      lev3 = row['Level 3'] 


     #if row['Level 4'] is not None and row['Level 4'] is not lev4: 
     # lev4_list.append({'name':lev4,'type':'concept','level':4}) 
     # lev4 = row['Level 4'] 

    i += 1 

f.close() 


branch_list.append({'name':branch,'type':'branch','children':lev1_list}) 

#subject_list.append({'name':subject,'type':'subject','children':branch_list}) 
subject_dict = {'name':subject,'type':'subject','children':branch_list} 

#json_list= json.dumps(subject_list) 
json_list = json.dumps(subject_dict) 

f = open('/Users/thaymore/Sites/d3/data/trig_map.json','wb') 
f.write(json_list) 
f.close() 

Quello che mi fa adesso è qualcosa di simile :

{"type": "subject", "name": "MAT", "children": [{"type": "branch", "name": "TRI", "children": [{"children": [{"children": [{"size": 40, "type": "concept", "name": "The Pythagorean Theorem", "level": 3}, {"size": 19, "type": "concept", "name": "Pythagorean Triples", "level": 3}, {"size": 68, "type": "concept", "name": "Converse of the Pythagorean Theorem", "level": 3}], "type": "concept", "name": "The Pythagorean Theorem", "level": 2}, {"children": [{"size": 28, "type": "concept", "name": "The Distance Formula", "level": 3}, {"size": 49, "type": "concept", "name": "Special Right Triangle #1: Isosceles Right Triangle", "level": 3}, {"size": 33, "type": "concept", "name": "Special Right Triangle #2: 30-60-90 Triangle", "level": 3}], "type": "concept", "name": "Special Right Triangles", "level": 2}, {"children": [{"size": 18, "type": "concept", "name": "Using Special Right Triangle Ratios", "level": 3}, {"size": 49, "type": "concept", "name": "The Sine, Cosine, and Tangent Functions", "level": 3}], "type": "concept", "name": "Basic Trigonometric Functions", "level": 2}, {"children": [{"size": 100, "type": "concept", "name": "Secant, Cosecant, and Cotangent Functions", "level": 3}, {"size": 73, "type": "concept", "name": "Solving Right Triangles", "level": 3}, {"size": 93, "type": "concept", "name": "Inverse Trigonometric Functions", "level": 3}, {"size": 88, "type": "concept", "name": "Finding the Area of a Triangle", "level": 3}, {"size": 6, "type": "concept", "name": "Angles of Elevation and Depression", "level": 3}, {"size": 3, "type": "concept", "name": "Right Triangles and Bearings", "level": 3}], "type": "concept", "name": "Solving Right Triangles", "level": 2}, {"children": [{"size": 68, "type": "concept", "name": "Other Applications of Right Triangles", "level": 3}, {"size": 92, "type": "concept", "name": "Angles of Rotation in Standard Position", "level": 3}], "type": "concept", "name": "Measuring Rotation", "level": 2}, {"children": [{"size": 14, "type": "concept", "name": "Coterminal Angles", "level": 3}, {"size": 68, "type": "concept", "name": "Trigonometric Functions of Angles in Standard Position", "level": 3}], "type": "concept", "name": "Applying Trig Functions to Angles of Rotation", "level": 2}, {"children": [{"size": 61, "type": "concept", "name": "The Unit Circle", "level": 3}, {"size": 95, "type": "concept", "name": "Reference Angles and Angles in the Unit Circle", "level": 3}, {"size": 11, "type": "concept", "name": "Trigonometric Functions of Negative Angles", "level": 3}, {"size": 45, "type": "concept", "name": "Trigonometric Functions of Angles Greater than 360 Degrees", "level": 3}], "type": "concept", "name": "Trigonometric Functions of Any Angle", "level": 2}], "type": "concept", "name": "Right Triangles and an Introduction to Trigonometry", "level": 1}, {"children": [{"children": [{"size": 20, "type": "concept", "name": "Using a Calculator to Find Values", "level": 3}, {"size": 25, "type": "concept", "name": "Reciprocal identities", "level": 3}, {"size": 40, "type": "concept", "name": "Domain, Range, and Signs of Trig Functions", "level": 3}, {"size": 97, "type": "concept", "name": "Quotient Identities", "level": 3}, {"size": 18, "type": "concept", "name": "Cofunction Identities and Reflection", "level": 3}], "type": "concept", "name": "Relating Trigonometric Functions", "level": 2}, {"children": [{"size": 35, "type": "concept", "name": "Pythagorean Identities", "level": 3}, {"size": 95, "type": "concept", "name": "Understanding Radian Measure", "level": 3}, {"size": 30, "type": "concept", "name": "Critial Angles in Radians", "level": 3}, {"size": 16, "type": "concept", "name": "Converting Any Degree to Radians", "level": 3}, {"size": 25, "type": "concept", "name": "The Six Trig Functions and Radians", "level": 3}], "type": "concept", "name": "Radian Measure", "level": 2}, {"children": [{"size": 19, "type": "concept", "name": "Check the Mode", "level": 3}, {"size": 63, "type": "concept", "name": "Rotations", "level": 3}, {"size": 33, "type": "concept", "name": "Length of Arc", "level": 3}, {"size": 54, "type": "concept", "name": "Area of a Sector", "level": 3}, {"size": 6, "type": "concept", "name": "Length of a Chord", "level": 3}], "type": "concept", "name": "Applications of Radian Measure", "level": 2}, {"children": [{"size": 71, "type": "concept", "name": "Angular Velocity", "level": 3}, {"size": 16, "type": "concept", "name": "The Sine Graph", "level": 3}, {"size": 65, "type": "concept", "name": "The Cosine Graph", "level": 3}, {"size": 32, "type": "concept", "name": "The Tangent Graph", "level": 3}, {"size": 93, "type": "concept", "name": "The Three Reciprocal Functions", "level": 3}, {"size": 30, "type": "concept", "name": "Cotangent", "level": 3}, {"size": 4, "type": "concept", "name": "Cosecant", "level": 3}], "type": "concept", "name": "Circular Functions of Real Numbers", "level": 2}, {"children": [{"size": 100, "type": "concept", "name": "Secant", "level": 3}, {"size": 40, "type": "concept", "name": "Vertical Translations", "level": 3}], "type": "concept", "name": "Translating Sine and Cosine Functions", "level": 2}, {"children": [{"size": 58, "type": "concept", "name": "Horizontal Translations or Phase Shifts", "level": 3}, {"size": 76, "type": "concept", "name": "Amplitude", "level": 3}, {"size": 91, "type": "concept", "name": "Period and Frequency", "level": 3}], "type": "concept", "name": "Amplitude, Period and Frequency", "level": 2}, {"children": [{"size": 78, "type": "concept", "name": "Combining Amplitude and Period", "level": 3}, {"size": 12, "type": "concept", "name": "The Generalized Equations", "level": 3}, {"size": 22, "type": "concept", "name": "Drawing Sketches/Identifying Transformations from the Equation", "level": 3}], "type": "concept", "name": "General Sinusoidal Graphs", "level": 2}], "type": "concept", "name": "Graphing Trigonometric Functions - 2nd edition", "level": 1}, {"children": [{"children": [{"size": 81, "type": "concept", "name": "Writing the Equation from a Sketch", "level": 3}, {"size": 60, "type": "concept", "name": "Tangent and Cotangent", "level": 3}, {"size": 27, "type": "concept", "name": "Secant and Cosecant", "level": 3}], "type": "concept", "name": "Graphing Tangent, Cotangent, Secant, and Cosecant", "level": 2}, {"children": [{"size": 62, "type": "concept", "name": "Graphing Calculator Note", "level": 3}, {"size": 20, "type": "concept", "name": "Quotient Identity", "level": 3}, {"size": 15, "type": "concept", "name": "Reciprocal Identities", "level": 3}, {"size": 28, "type": "concept", "name": "Pythagorean Identity", "level": 3}, {"size": 28, "type": "concept", "name": "Even and Odd Identities", "level": 3}], "type": "concept", "name": "Fundamental Identities", "level": 2}, {"children": [{"size": 24, "type": "concept", "name": "Cofunction Identities", "level": 3}, {"size": 91, "type": "concept", "name": "Working with Trigonometric Identities", "level": 3}], "type": "concept", "name": "Proving Identities", "level": 2}, {"children": [{"size": 59, "type": "concept", "name": "Technology Note", "level": 3}, {"size": 26, "type": "concept", "name": "Simplifying Trigonometric Expressions", "level": 3}, {"size": 94, "type": "concept", "name": "Solving Trigonometric Equations", "level": 3}, {"size": 49, "type": "concept", "name": "Solving Trigonometric Equations Using Factoring", "level": 3}], "type": "concept", "name": "Solving Trigonometric Equations", "level": 2}, {"children": [{"size": 25, "type": "concept", "name": "Solving Trigonometric Equations Using the Quadratic Formula", "level": 3}, {"size": 11, "type": "concept", "name": "Sum and Difference Formulas: cosine", "level": 3}, {"size": 30, "type": "concept", "name": "Using the Sum and Difference Identities of cosine", "level": 3}, {"size": 75, "type": "concept", "name": "Sum and Difference Identities: sine", "level": 3}, {"size": 94, "type": "concept", "name": "Sum and Difference Identities: Tangent", "level": 3}, {"size": 22, "type": "concept", "name": "Using the Sum and Difference Identities to Verify Other Identities", "level": 3}], "type": "concept", "name": "Sum and Difference Identities", "level": 2}, {"children": [{"size": 15, "type": "concept", "name": "Solving Equations with the Sum and Difference Formulas", "level": 3}, {"size": 88, "type": "concept", "name": "Deriving the Double Angle Identities", "level": 3}, {"size": 42, "type": "concept", "name": "Applying the Double Angle Identities", "level": 3}], "type": "concept", "name": "Double Angle Identities", "level": 2}, {"children": [{"size": 13, "type": "concept", "name": "Solving Equations with Double Angle Identities", "level": 3}, {"size": 36, "type": "concept", "name": "Deriving the Half Angle Formulas", "level": 3}], "type": "concept", "name": "Half-Angle Identities", "level": 2}], "type": "concept", "name": "Trigonometric Identities and Equations - 2nd edition", "level": 1}, {"children": [{"children": [{"size": 100, "type": "concept", "name": "Solving Trigonometric Equations Using Half Angle Formulas", "level": 3}, {"size": 93, "type": "concept", "name": "Sum to Product Formulas for Sine and Cosine", "level": 3}, {"size": 71, "type": "concept", "name": "Product to Sum Formulas for Sine and Cosine", "level": 3}, {"size": 53, "type": "concept", "name": "Solving Equations with Product and Sum Formulas", "level": 3}, {"size": 45, "type": "concept", "name": "Triple-Angle Formulas and Beyond", "level": 3}, {"size": 18, "type": "concept", "name": "Linear Combinations", "level": 3}], "type": "concept", "name": "Products, Sums, Linear Combinations, and Applications", "level": 2}, {"children": [{"size": 73, "type": "concept", "name": "Applications & Technology", "level": 3}, {"size": 54, "type": "concept", "name": "Defining the Inverse of the Trigonometric Ratios", "level": 3}, {"size": 15, "type": "concept", "name": "Exact Values for Inverse Sine, Cosine, and Tangent", "level": 3}], "type": "concept", "name": "Basic Inverse Trigonometric Functions", "level": 2}, {"children": [{"size": 1, "type": "concept", "name": "Finding Inverses Algebraically", "level": 3}, {"size": 93, "type": "concept", "name": "Finding the Inverse by Mapping", "level": 3}], "type": "concept", "name": "Graphing Inverse Trigonometric Functions", "level": 2}, {"children": [{"size": 79, "type": "concept", "name": "Finding the Inverse of the Trigonometric Functions", "level": 3}, {"size": 29, "type": "concept", "name": "Composing Trig Functions and their Inverses", "level": 3}, {"size": 19, "type": "concept", "name": "Composing Trigonometric Functions", "level": 3}, {"size": 53, "type": "concept", "name": "Inverse Reciprocal Functions", "level": 3}, {"size": 28, "type": "concept", "name": "Composing Inverse Reciprocal Trig Functions", "level": 3}], "type": "concept", "name": "Inverse Trigonometric Properties", "level": 2}], "type": "concept", "name": "Inverse Trigonometric Functions - 2nd edition", "level": 1}, {"children": [{"children": [], "type": "concept", "name": "Applications & Models", "level": 2}, {"children": [{"size": 42, "type": "concept", "name": "Trigonometry in Terms of Algebra", "level": 3}, {"size": 38, "type": "concept", "name": "Derive the Law of Cosines", "level": 3}, {"size": 82, "type": "concept", "name": "Case #1: Finding the Side of an Oblique Triangle", "level": 3}, {"size": 68, "type": "concept", "name": "Case #2: Finding any Angle of a Triangle", "level": 3}], "type": "concept", "name": "The Law of Cosines", "level": 2}, {"children": [{"size": 20, "type": "concept", "name": "Identify Accurate Drawings of General Triangles", "level": 3}, {"size": 90, "type": "concept", "name": "Find the Area Using Three Sides: Heron\u2019s Formula", "level": 3}, {"size": 7, "type": "concept", "name": "Heron\u2019s Formula:", "level": 3}], "type": "concept", "name": "Area of a Triangle", "level": 2}, {"children": [{"size": 21, "type": "concept", "name": "Finding a Part of the Triangle, Given the Area", "level": 3}, {"size": 58, "type": "concept", "name": "Deriving the Law of Sines", "level": 3}, {"size": 15, "type": "concept", "name": "AAS (Angle-Angle-Side)", "level": 3}, {"size": 41, "type": "concept", "name": "ASA (Angle-Side-Angle)", "level": 3}], "type": "concept", "name": "The Law of Sines", "level": 2}, {"children": [{"size": 87, "type": "concept", "name": "Solving Triangles", "level": 3}, {"size": 31, "type": "concept", "name": "Possible Triangles with SSA", "level": 3}, {"size": 45, "type": "concept", "name": "Using the Law of Sines", "level": 3}], "type": "concept", "name": "The Ambiguous Case", "level": 2}, {"children": [{"size": 40, "type": "concept", "name": "Using the Law of Cosines", "level": 3}, {"size": 2, "type": "concept", "name": "Summary of Triangle Techniques", "level": 3}, {"size": 18, "type": "concept", "name": "Using the Law of Cosines", "level": 3}], "type": "concept", "name": "General Solutions of Triangles", "level": 2}, {"children": [{"size": 42, "type": "concept", "name": "Using the Law of Sines", "level": 3}, {"size": 6, "type": "concept", "name": "Directed Line Segments, Equal Vectors, and Absolute Value", "level": 3}, {"size": 60, "type": "concept", "name": "Vector Addition", "level": 3}, {"size": 76, "type": "concept", "name": "Vector Subtraction", "level": 3}], "type": "concept", "name": "Vectors", "level": 2}], "type": "concept", "name": "Triangles and Vectors", "level": 1}]}]} 

Penso che questo potrebbe tecnicamente adattarsi alle specifiche JSON, ma la libreria che Sto cercando di fornire i dati JSON a (D3.js) non sembra che possa farci niente. È perché l'ordine degli elementi è fuori questione (vale a dire, l'elemento "bambini" viene prima dell'elemento "nome")? È qualcosa di più fondamentale che sto facendo?

(Il file la cui struttura che sto cercando di abbinare si trova here.)

+0

Controllare se è l'ordine cambiando tutti i '{}'/'dict's con' OrderedDict's e riportare. – agf

+0

Cosa intendi con _ "non riesco a farci niente" _? Impossibile analizzarlo (ad esempio, forse la virgola in più alla fine dell'esempio sta causando un errore di analisi) o qualcosa di più specifico? –

+0

@agf Running Python 2.6 - OrderedDict è disponibile in quella versione? – tchaymore

risposta

6

Non sarebbe questo lavoro?

import json 

f = open('path/to/file','r') 

arr=[] 
headers = [] 

for header in f.readline().split(','): 
    headers.append(header) 

for line in f.readlines(): 
    lineItems = {} 
    for i,item in enumerate(line.split(',')): 
    lineItems[headers[i]] = item 
    arr.append(lineItems) 

f.close() 

jsonText = json.dumps(arr) 

print jsonText 
0

L'ordine degli elementi non è importante per JSON.

Il fatto che tu stia producendo è sbagliato, però. L'esempio che hai fornito che stai cercando di abbinare non ha un tasto "soggetto" al livello più alto. Mostra solo "name" => "flare" e una lista di bambini. La tua sceneggiatura sta producendo JSON con una chiave "soggetto".

Invece di

subject_dict = {'name':subject,'type':'subject','children':branch_list} 

provare

subject_dict = {'name':subject,'children':branch_list} 

Non so su d3.js, quindi non posso dire se si aspetta un oggetto che segue una struttura esatta.

Suggerimento: uno strumento valido per verificare la struttura degli oggetti JSON è http://jsoneditor.appspot.com. Basta incollare la stringa lì e fare clic su "Vai a Treeview". Sarà difficile trovare le differenze tra ciò che hai e ciò che vuoi molto facilmente.

-1
import csv 
import json 
file1 = csv.DictReader(open('filename.csv', 'r')) 
output =[] 
for each in complent: 
    row = {} 
    row['Id'] = each['Id'] 
    row['Name'] = each['Name'] 
    row['Address'] = each['Address'] 
    row['Mobile'] = each['Mobile'] 
    row['LandLine'] = each['LandLine'] 
    row['Email'] = each['Email'] 
    output.append(row) 

json.dump(output,open('new_file.json','w'),indent=4,sort_keys=False) 
0

D3 si aspetta che il valore in JSON sia anche tra virgolette. quindi ad es. "livello": 3 dovrebbe essere "livello": "3". Quando si utilizzano questi dati in D3 per il calcolo, sarà necessario essere di nuovo un numero sebbene così dove lo si utilizza è possibile utilizzare + data.xxx.yyy.level invece di data.xxx.yyy.level nel codice d3 da attivare in un numero.