2013-04-28 21 views
10

Vorrei eseguire il dump di un dizionario Python in un file JSON con un particolare formato personalizzato. Ad esempio, il seguente dizionario my_dict,Formattazione JSON formattazione personalizzata

'text_lines': [{"line1"}, {"line2"}] 

scaricato con

f.write(json.dumps(my_dict, sort_keys=True, indent=2)) 

assomiglia a questo

"text_lines": [ 
    { 
     "line1" 
    }, 
    { 
     "line2" 
    } 
    ] 

mentre io preferisco che assomiglia a questo

"text_lines": 
    [ 
    {"line1"}, 
    {"line2"} 
    ] 

Simila rly, voglio il seguente

"location": [ 
    22, 
    -8 
    ] 

a guardare come questo

"location": [22, -8] 

(vale a dire, più simile a una coordinata, che è).

So che questo è un problema estetico, ma è importante per me conservare questa formattazione per facilitare la modifica manuale del file.

Qualsiasi modo di fare questo tipo di personalizzazione? Un esempio spiegato sarebbe ottimo (i documenti non mi hanno portato molto lontano).

+1

Questo, BTW, non è un JSON valido ... ha funzionato? – SuperSaiyan

+1

Non per scherzare sul punto, ma i tuoi doni json non sono ancora validi. (ad esempio, ogni dict ha bisogno di una chiave e di un valore: {"line1": "valore1}). Hai mai capito come usare JSONEncoder per farlo: –

risposta

2

Sarà necessario creare una sottoclasse della classe json.JSONEncoder e sovrascrivere i metodi per ciascun tipo di valore in modo che scrivano il formato necessario. Si può finire per ri-implementare la maggior parte di loro, a seconda di quali sono le vostre esigenze di formattazione.

http://docs.python.org/2/library/json.html ha un esempio per l'estensione di JSONEncoder.

+1

Un esempio sarebbe bello. come utilizzare JSONEncoder per fare ciò. –

3

Ecco qualcosa che ho hackerato insieme. Non molto carina ma sembra funzionare. Probabilmente potresti gestire semplici dizionari in modo simile.

class MyJSONEncoder(json.JSONEncoder): 
    def __init__(self, *args, **kwargs): 
     super(MyJSONEncoder, self).__init__(*args, **kwargs) 
     self.current_indent = 0 
     self.current_indent_str = "" 

    def encode(self, o): 
     #Special Processing for lists 
     if isinstance(o, (list, tuple)): 
      primitives_only = True 
      for item in o: 
       if isinstance(item, (list, tuple, dict)): 
        primitives_only = False 
        break 
      output = [] 
      if primitives_only: 
       for item in o: 
        output.append(json.dumps(item)) 
       return "[ " + ", ".join(output) + " ]" 
      else: 
       self.current_indent += self.indent 
       self.current_indent_str = "".join([ " " for x in range(self.current_indent) ]) 
       for item in o: 
        output.append(self.current_indent_str + self.encode(item)) 
       self.current_indent -= self.indent 
       self.current_indent_str = "".join([ " " for x in range(self.current_indent) ]) 
       return "[\n" + ",\n".join(output) + "\n" + self.current_indent_str + "]" 
     elif isinstance(o, dict): 
      output = [] 
      self.current_indent += self.indent 
      self.current_indent_str = "".join([ " " for x in range(self.current_indent) ]) 
      for key, value in o.iteritems(): 
       output.append(self.current_indent_str + json.dumps(key) + ": " + self.encode(value)) 
      self.current_indent -= self.indent 
      self.current_indent_str = "".join([ " " for x in range(self.current_indent) ]) 
      return "{\n" + ",\n".join(output) + "\n" + self.current_indent_str + "}" 
     else: 
      return json.dumps(o) 

NOTA: E 'praticamente inutile in questo codice da ereditando da JSONEncoder.

+1

Nota che puoi sostituire "" ".join ([" "per x nell'intervallo (self.current_indent)])' with '" "* self.current_indent' ;-) – Johan