2010-09-09 11 views
5

Jestem całkiem nowy dla Pythona (używam Pythona 3) i próbuję serializować klasę z jednym ciągiem i dwoma listami jako członkami w JSon. Znalazłem json lib w standardzie Pythona, ale wydaje się, że muszę ręcznie wdrożyć metodę serializacji. Czy istnieje koder JSon, w którym mogę po prostu przekazać obiekt i odebrać serializowany obiekt jako ciąg bez konieczności implementowania metody serializacji. Przykład:Łatwe kodowanie JSON z Pythonem

class MyClass: 
    pass 

if __name__ == '__main__': 
    my_name = "me" 
    my_list = {"one","two"} 
    my_obj = MyClass() 
    my_obj.name = my_name; 
    my_obj.my_list = my_list 


    serialized_object = JSONserializer.serialize(my_obj). 

Dziękuję.

+0

Czy wersja Pythona jest ważna? Mam na myśli, czy jesteś w stanie to zrobić w wersji 2.x, ale nie możesz tego zrobić w wersji 3.0? – esylvestre

+0

Tak, wygląda na to, że większość bibliotek zmieniła się z 2.x na 3. –

Odpowiedz

3

nie wiem o niczym gotowych, ale można napisać, jeśli obiekty są dość proste. Zastąp domyślną metodę w JSONEncoderze, aby przejrzeć inspect.getmembers (obj) (inspekcja jest bardziej czytelnym sposobem uzyskania zestawów atrybutów w __dict__).

#!/usr/bin/env python3 

import inspect 
from json import JSONEncoder 


class TreeNode: 

    def __init__(self, value, left=None, right=None): 
     self.value = value 
     self.left = left 
     self.right = right 


class ObjectJSONEncoder(JSONEncoder): 

    def default(self, reject): 
     is_not_method = lambda o: not inspect.isroutine(o) 
     non_methods = inspect.getmembers(reject, is_not_method) 
     return {attr: value for attr, value in non_methods 
       if not attr.startswith('__')} 


if __name__ == '__main__': 
    tree = TreeNode(42, 
     TreeNode(24), 
     TreeNode(242), 
    ) 
    print(ObjectJSONEncoder().encode(tree)) 

Aktualizacja: @Alexandre Deschamps mówi isroutine działa lepiej niż metoda jakiegoś wejścia.

+0

Dziękuję za anwser, to prawie robi lewę, z wyjątkiem dwóch rzeczy. Metoda is_not_method = lambda o: not inspect.ismetod (o) wydaje się również wymagać instrukcji not inspect.isroutine (o). Wygląda na to, że w pythonie wbudowana metoda jest przypadkiem ograniczającym. Ponadto, moja klasa potrzebuje listy do serializacji. wygląda na to, że elementy na liście nie są z nim serializowane. –

+0

@Alexandre Deschamps: Nie mówię o tym, co masz na myśli ... jeśli zmienisz te liczby w '__main__' na listy liczb, to serializowanie jest w porządku. – cdleary

+0

Ok, właśnie dowiedziałem się, że jestem problem. Używałem {} zamiast [] do utworzenia listy. Jak już powiedziałem, jestem nowy w tym języku. To działa dobrze. Po prostu dodaj "nie inspect.isroutine" do swojego przykładu na wypadek, gdyby inne osoby tego potrzebowały. Wielkie dzięki za twój czas. –

0

Co z klasą JSONEncoder?

aktualizacja

Musiałem pomijane części o dane zawarte są w klasie. Jeśli chcesz uzyskać porządek serializacji dowolnych obiektów w Pythonie bez potrzeby rozszerzania kodera, możesz użyć kombinacji pickle i json. Podczas pikowania użyj protokołu = 0, aby przekształcić dane w postaci czytelnej dla człowieka, ASCII.

+0

Nadal muszę zakodować klasę, a nie tylko prosty typ lub tablicę. Ta klasa wydaje się wymagać ręcznie zdefiniowanej metody serializacji w celu serializacji klasy. Może się mylę, odkąd jestem nowy w tym języku, ale kiedy testowałem, to właśnie dostałem. –

+0

@Alexandre - zaktualizowane moją odpowiedź –

+0

'pomysł pickle' z dnia czytelny dla człowieka jest:' (i__main__ mapą p0 (DP1 S'towers' p2 (LP3 (i__main__ Wieża p4 (DP5 S'attack ' P6 I10 sbasS'creeps' P7 (lp8 S'one strun pełzania na liście' P9 asb.' porównaniu do JSON, który jest ledwo czytelny dla człowieka. – Pat

4

Jak można się spodziewać biblioteki json wiedzieć, jak serializować dowolne klasy?

W twoim przypadku, jeśli klasa jest na tyle prosty, może być w stanie uciec coś

foo = FooObject() # or whatever 
json_string = json.dumps(foo.__dict__) 

tylko szeregować członków obiektu.

Deserializacji będzie wtedy trzeba być coś

foo_data = json.loads(json_string) 
foo = FooObject(**foo_data) 
+0

Nie, wydaje się, że działa, ponieważ moja klasa ma dwóch członków, co jest ciągiem znaków i listą ciągów znaków –

+0

Działa to dla mnie: http://gist.github.com/574291. Jeśli twój obiekt ma naprawdę tylko dwóch członków, łańcuch i listę łańcuchów, to serializacja będzie działać. Technika deserializacji, której używam, polega na funkcji '__init__' używanej przez twojego obiektu do przyjmowania argumentów o tych samych nazwach co członkowie. Zobacz powyższy fragment, aby uzyskać przykład działania. –

+0

@WillMcCutchen Dzięki za inspirację do użycia 'dict'. Chciałem zrobić coś podobnego i chociaż mój obiekt (z żądania SOAP) nie miał metody "__dict__", wywołanie 'dict (soapObj) dało mi ładnie wydrukowany ciąg JSON. Jestem też nowy w Pythonie i nie jest to oczywista technika, więc cieszę się, że o tym wspomniałeś! – Pat