Got deserialization working properly
This commit is contained in:
@@ -17,7 +17,7 @@ def main():
|
||||
password=sys.argv[2])
|
||||
|
||||
# print(server.ping())
|
||||
# print(server.get_license())
|
||||
print(server.get_license())
|
||||
print(server.get_music_folders())
|
||||
# print(server.get_indexes())
|
||||
# print()
|
||||
|
@@ -1,5 +1,6 @@
|
||||
import inspect
|
||||
from typing import Dict, List, Any
|
||||
import typing
|
||||
from typing import Dict, List, Any, Type
|
||||
from datetime import datetime
|
||||
from dateutil import parser
|
||||
|
||||
@@ -9,25 +10,37 @@ def _from_json(cls, data):
|
||||
Approach for deserialization here:
|
||||
https://stackoverflow.com/a/40639688/2319844
|
||||
"""
|
||||
print(cls, data)
|
||||
annotations: Dict[str, Any] = getattr(cls, '__annotations__', {})
|
||||
annotations: Dict[str, Type] = getattr(cls, '__annotations__', {})
|
||||
|
||||
# Handle lists of objects.
|
||||
if cls == str:
|
||||
return data
|
||||
if issubclass(cls, List):
|
||||
list_type = cls.__args__[0]
|
||||
instance: List[list_type] = list()
|
||||
for value in data:
|
||||
instance.append(_from_json(list_type, value))
|
||||
instance = data
|
||||
elif cls == int:
|
||||
instance = int(data)
|
||||
elif cls == bool:
|
||||
instance = bool(data)
|
||||
elif cls == datetime:
|
||||
instance = parser.parse(data)
|
||||
elif type(cls) == typing._GenericAlias:
|
||||
# Having to use this because things changed in Python 3.7.
|
||||
|
||||
# Handle dictionaries of objects.
|
||||
elif issubclass(cls, Dict):
|
||||
key_type, val_type = cls.__args__
|
||||
instance: Dict[key_type, val_type] = dict()
|
||||
for key, value in data.items():
|
||||
instance.update(_from_json(key_type, key),
|
||||
_from_json(val_type, value))
|
||||
# No idea what the heck this is, but let's go with it.
|
||||
if cls._name == 'List':
|
||||
list_type = cls.__args__[0]
|
||||
instance: List[list_type] = list()
|
||||
for value in data:
|
||||
instance.append(_from_json(list_type, value))
|
||||
|
||||
elif cls._name == 'Dict':
|
||||
key_type, val_type = cls.__args__
|
||||
instance: Dict[key_type, val_type] = dict()
|
||||
for key, value in data.items():
|
||||
key = _from_json(key_type, key)
|
||||
value = _from_json(val_type, value)
|
||||
instance[key] = value
|
||||
else:
|
||||
raise Exception(
|
||||
'Trying to deserialize an unsupported type: {cls._name}')
|
||||
|
||||
# Handle everything else by first instantiating the class, then adding
|
||||
# all of the sub-elements, recursively calling from_json on them.
|
||||
@@ -35,11 +48,10 @@ def _from_json(cls, data):
|
||||
instance: cls = cls()
|
||||
for name, value in data.items():
|
||||
field_type = annotations.get(name)
|
||||
print('ohea', field_type, value)
|
||||
if inspect.isclass(field_type):
|
||||
|
||||
# Sometimes there are extraneous values, ignore them.
|
||||
if field_type:
|
||||
setattr(instance, name, _from_json(field_type, value))
|
||||
else:
|
||||
setattr(instance, name, value)
|
||||
|
||||
return instance
|
||||
|
||||
@@ -74,6 +86,7 @@ class License(APIObject):
|
||||
valid: bool
|
||||
email: str
|
||||
licenseExpires: datetime
|
||||
trialExpires: datetime
|
||||
|
||||
|
||||
class MusicFolder(APIObject):
|
||||
@@ -86,4 +99,4 @@ class SubsonicResponse(APIObject):
|
||||
version: str
|
||||
license: License
|
||||
error: SubsonicError
|
||||
musicFolders: List[MusicFolder]
|
||||
musicFolders: Dict[str, List[MusicFolder]]
|
||||
|
@@ -51,7 +51,9 @@ class Server:
|
||||
|
||||
def get_music_folders(self):
|
||||
result = self._post(self._make_url('getMusicFolders'))
|
||||
return result.musicFolders
|
||||
# The Airsonic API implementation of this is dumb. It gives totally the
|
||||
# wrong answer so we have to go in to the 'musicFolder' key here.
|
||||
return result.musicFolders['musicFolder']
|
||||
|
||||
def get_indexes(self):
|
||||
result = self._post(self._make_url('getIndexes'))
|
||||
|
Reference in New Issue
Block a user