models: Support automatic serialization to and deserialization from JSON
This commit is contained in:
parent
f237736f87
commit
68e4b207cb
@ -1,5 +1,7 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
class ImmutableObject(object):
|
class ImmutableObject(object):
|
||||||
"""
|
"""
|
||||||
@ -91,6 +93,49 @@ class ImmutableObject(object):
|
|||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
class ModelJSONEncoder(json.JSONEncoder):
|
||||||
|
"""
|
||||||
|
Automatically serialize Mopidy models to JSON.
|
||||||
|
|
||||||
|
Usage::
|
||||||
|
|
||||||
|
>>> import json
|
||||||
|
>>> json.dumps({'a_track': Track(name='name')}, cls=ModelJSONEncoder)
|
||||||
|
'{"a_track": {"__type__": "Track", "name": "name"}}'
|
||||||
|
|
||||||
|
"""
|
||||||
|
def default(self, obj):
|
||||||
|
if isinstance(obj, ImmutableObject):
|
||||||
|
return obj.serialize()
|
||||||
|
return json.JSONEncoder.default(self, obj)
|
||||||
|
|
||||||
|
|
||||||
|
def model_json_decoder(dct):
|
||||||
|
"""
|
||||||
|
Automatically deserialize Mopidy models from JSON.
|
||||||
|
|
||||||
|
Usage::
|
||||||
|
|
||||||
|
>>> import json
|
||||||
|
>>> json.loads(
|
||||||
|
... '{"a_track": {"__type__": "Track", "name": "name"}}',
|
||||||
|
... object_hook=model_json_decoder)
|
||||||
|
{u'a_track': Track(artists=[], name=u'name')}
|
||||||
|
|
||||||
|
"""
|
||||||
|
if '__type__' in dct:
|
||||||
|
obj_type = dct.pop('__type__')
|
||||||
|
if obj_type == 'Album':
|
||||||
|
return Album(**dct)
|
||||||
|
if obj_type == 'Artist':
|
||||||
|
return Artist(**dct)
|
||||||
|
if obj_type == 'Playlist':
|
||||||
|
return Playlist(**dct)
|
||||||
|
if obj_type == 'Track':
|
||||||
|
return Track(**dct)
|
||||||
|
return dct
|
||||||
|
|
||||||
|
|
||||||
class Artist(ImmutableObject):
|
class Artist(ImmutableObject):
|
||||||
"""
|
"""
|
||||||
:param uri: artist URI
|
:param uri: artist URI
|
||||||
|
|||||||
@ -1,8 +1,11 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
import json
|
||||||
|
|
||||||
from mopidy.models import Artist, Album, TlTrack, Track, Playlist
|
from mopidy.models import (
|
||||||
|
Artist, Album, TlTrack, Track, Playlist,
|
||||||
|
ModelJSONEncoder, model_json_decoder)
|
||||||
|
|
||||||
from tests import unittest
|
from tests import unittest
|
||||||
|
|
||||||
@ -86,6 +89,12 @@ class ArtistTest(unittest.TestCase):
|
|||||||
{'__type__': 'Artist', 'uri': 'uri', 'name': 'name'},
|
{'__type__': 'Artist', 'uri': 'uri', 'name': 'name'},
|
||||||
Artist(uri='uri', name='name').serialize())
|
Artist(uri='uri', name='name').serialize())
|
||||||
|
|
||||||
|
def test_to_json_and_Back(self):
|
||||||
|
artist1 = Artist(uri='uri', name='name')
|
||||||
|
serialized = json.dumps(artist1, cls=ModelJSONEncoder)
|
||||||
|
artist2 = json.loads(serialized, object_hook=model_json_decoder)
|
||||||
|
self.assertEqual(artist1, artist2)
|
||||||
|
|
||||||
def test_eq_name(self):
|
def test_eq_name(self):
|
||||||
artist1 = Artist(name='name')
|
artist1 = Artist(name='name')
|
||||||
artist2 = Artist(name='name')
|
artist2 = Artist(name='name')
|
||||||
@ -205,6 +214,12 @@ class AlbumTest(unittest.TestCase):
|
|||||||
[artist.serialize()]},
|
[artist.serialize()]},
|
||||||
Album(uri='uri', name='name', artists=[artist]).serialize())
|
Album(uri='uri', name='name', artists=[artist]).serialize())
|
||||||
|
|
||||||
|
def test_to_json_and_back(self):
|
||||||
|
album1 = Album(uri='uri', name='name', artists=[Artist(name='foo')])
|
||||||
|
serialized = json.dumps(album1, cls=ModelJSONEncoder)
|
||||||
|
album2 = json.loads(serialized, object_hook=model_json_decoder)
|
||||||
|
self.assertEqual(album1, album2)
|
||||||
|
|
||||||
def test_eq_name(self):
|
def test_eq_name(self):
|
||||||
album1 = Album(name='name')
|
album1 = Album(name='name')
|
||||||
album2 = Album(name='name')
|
album2 = Album(name='name')
|
||||||
@ -404,6 +419,14 @@ class TrackTest(unittest.TestCase):
|
|||||||
'album': album.serialize()},
|
'album': album.serialize()},
|
||||||
Track(uri='uri', name='name', album=album).serialize())
|
Track(uri='uri', name='name', album=album).serialize())
|
||||||
|
|
||||||
|
def test_to_json_and_back(self):
|
||||||
|
track1 = Track(
|
||||||
|
uri='uri', name='name', album=Album(name='foo'),
|
||||||
|
artists=[Artist(name='foo')])
|
||||||
|
serialized = json.dumps(track1, cls=ModelJSONEncoder)
|
||||||
|
track2 = json.loads(serialized, object_hook=model_json_decoder)
|
||||||
|
self.assertEqual(track1, track2)
|
||||||
|
|
||||||
def test_eq_uri(self):
|
def test_eq_uri(self):
|
||||||
track1 = Track(uri='uri1')
|
track1 = Track(uri='uri1')
|
||||||
track2 = Track(uri='uri1')
|
track2 = Track(uri='uri1')
|
||||||
@ -598,6 +621,12 @@ class TlTrackTest(unittest.TestCase):
|
|||||||
{'__type__': 'TlTrack', 'tlid': 123, 'track': track.serialize()},
|
{'__type__': 'TlTrack', 'tlid': 123, 'track': track.serialize()},
|
||||||
TlTrack(tlid=123, track=track).serialize())
|
TlTrack(tlid=123, track=track).serialize())
|
||||||
|
|
||||||
|
def test_to_json_and_back(self):
|
||||||
|
track1 = Track(uri='uri', name='name')
|
||||||
|
serialized = json.dumps(track1, cls=ModelJSONEncoder)
|
||||||
|
track2 = json.loads(serialized, object_hook=model_json_decoder)
|
||||||
|
self.assertEqual(track1, track2)
|
||||||
|
|
||||||
def test_eq(self):
|
def test_eq(self):
|
||||||
tlid = 123
|
tlid = 123
|
||||||
track = Track()
|
track = Track()
|
||||||
@ -733,6 +762,12 @@ class PlaylistTest(unittest.TestCase):
|
|||||||
'tracks': [track.serialize()]},
|
'tracks': [track.serialize()]},
|
||||||
Playlist(uri='uri', name='name', tracks=[track]).serialize())
|
Playlist(uri='uri', name='name', tracks=[track]).serialize())
|
||||||
|
|
||||||
|
def test_to_json_and_back(self):
|
||||||
|
playlist1 = Playlist(uri='uri', name='name')
|
||||||
|
serialized = json.dumps(playlist1, cls=ModelJSONEncoder)
|
||||||
|
playlist2 = json.loads(serialized, object_hook=model_json_decoder)
|
||||||
|
self.assertEqual(playlist1, playlist2)
|
||||||
|
|
||||||
def test_eq_name(self):
|
def test_eq_name(self):
|
||||||
playlist1 = Playlist(name='name')
|
playlist1 = Playlist(name='name')
|
||||||
playlist2 = Playlist(name='name')
|
playlist2 = Playlist(name='name')
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user