2013-03-06 4 views
2

J'ai un objet JSON qui ressemble à ceci:Aplatir un objet JSON avec d'autres objets JSON embarqués

 
{ 
    "name":"bacon" 
    "category":["food","meat","good"] 
    "calories":"huge" 
} 

Je suis en train d'aplatir que dans un tableau de valeurs uniques. J'ai besoin de construire une table de faits pour Tableau qui n'est pas capable de travailler directement avec des données croisées ou des données JSON.

Je ne suis pas difficile à savoir si je le fais en Python ou Ruby, mais jusqu'ici j'ai essayé de le faire dans Ruby. Je suis capable de facilement analyser le JSON et obtenir un hachage Ruby qui semble être la bonne chose à faire en premier.

 
{"name"=>"bacon", "category"=>["food", "meat", "good"], "calories" => "huge"} 

et je dois produire ceci:

name,category,calories 
bacon,food,huge 
bacon,meat,huge 
bacon,good,huge 

Je pense que je dois faire une boucle à travers ce hachage et essayer de non imbriquer. Je l'ai expérimenté avec quelque chose comme ceci:

def Flatten(inHash) 
    inHash.each do |key,value| 
     if value.kind_of?(Hash) 
      Flatten(value) 
     else 
      puts "#{value}" 
     end 
    end 
end 

Mais et qui semble imprimer toutes les valeurs, mais il ne se répète pas la valeur qui est venu avant. Donc, je reçois la sortie qui ressemble

bacon 
food 
meat 
good 
huge 

Y at-il une méthode intégrée ou bijou ou bibliothèque qui ceci ou que je cherche à construire à partir de zéro? Des idées sur la façon d'obtenir la sortie que je veux? Je parle Ruby et Python donc si vous avez une réponse Python s'il vous plaît partager.

+0

Est-ce que '{" name ":" bacon "" category ": [" nourriture "," viande "," bon "]" calories ":" énorme "}' un objet json valide en Python? – Sibi

Répondre

2
>>> #Assuming your json data is correctly formatted as is as follows 
>>> data = '{ "name":"bacon", "category":["food","meat","good"], "calories":"huge" }' 
>>> #Lets call our json parser as foo (I am bad with names) 
>>> def foo(data): 
    #You first need to parse it to a Py Object 
    json_data = json.loads(data) 
    from collections import namedtuple 
    #Now create a namedtuple with the given keys of the dictionary 
    food_matrix = namedtuple('food_matrix',json_data.keys()) 
    #And create a tuple out of the values 
    data_tuple = food_matrix(*json_data.values()) 
    #Now with itertools.product create a cross product 
    from itertools import product 
    data_matrix = list(product([data_tuple.name],data_tuple.category, [data_tuple.calories])) 
    # Now display the heading 
    print "{:15}{:15}{:15}".format(["name","category","calories") 
    # Now display the values 
    for e in data_matrix: 
     print "{:15}{:15}{:15}".format(*e) 


>>> #Now call it 
>>> foo(data) 
name   category  calories     
bacon   food   huge   
bacon   meat   huge   
bacon   good   huge   
>>> 
0

En supposant que votre JSON a des virgules (pour le rendre valid JSON), vous pouvez utiliser itertools.product d'énumérer toutes les combinaisons possibles:

import itertools as IT 
import json 

text = '{ "name":"bacon", "category":["food","meat","good"], "calories":"huge" }' 
data = json.loads(text) 

# Sort the keys in the order they appear in `text` 
keys = sorted(data.keys(), key = lambda k: text.index(k)) 

# Promote the values to lists if they are not already lists 
values = [data[k] if isinstance(data[k], list) else [data[k]] for k in keys] 

print(','.join(keys)) 
for row in IT.product(*values): 
    print(','.join(row)) 

rendements

name,category,calories 
bacon,food,huge 
bacon,meat,huge 
bacon,good,huge 
0

serait ici ma solution:

require 'json' 

# Given a json object 
json = JSON.parse('{"name":"bacon", "category":["food","meat","good"], "calories":"huge"}') 

# First, normalize all the values to arrays 
hash = Hash[json.map{|k, v| [k, [v].flatten]}] 

# We now have a hash like {"name" => ["bacon"], ...} 

# Then we'll make the product of the first array of values 
# (in this case, ["bacon"]) with the other values 
permutations = hash.values[0].product(*hash.values[1..-1]) 

# Now just need to output 
puts hash.keys.join(",") 
permutations.each{ |group| puts group.join(",") } 
+0

Notez que cela fonctionnera uniquement dans Ruby 1.9+, car il suppose un hachage ordonné. Vous pouvez obtenir la même chose dans Ruby 1.8 en ignorant la reconversion de la conversion de hachage et en utilisant des tableaux comme '[" name ", [" bacon "]]' – gmalette