I have to convert a data structure to an object. This data structure can consist of any number of nested lists and dictionaries. I have written code that is currently capable of doing this as long as the input data is a dictionary on the highest level. if the input data is a list then this will not work because there is no initial key to create an attribute from. The functionality I'm looking for would have this class return a list if the input data is a list.
My current code is as follows:
class DataConverter(object):
def __init__(self, data):
if isinstance(data, dict):
for key in data:
value = data[key]
if isinstance(value, list):
new_list = []
for ind in value:
if isinstance(ind, dict):
new_list.append(DataConverter(ind))
else:
new_list.append(ind)
setattr(self, key, new_list)
elif isinstance(value, dict):
setattr(self, key, DataConverter(value))
else:
setattr(self, key, value)
elif isinstance(data, list):
new_list = []
for val in data:
new_list.append(DataConverter(val))
# TODO: class needs to init as 'new_list' if it gets here
the input data will be in structures similar to this but 1000x larger and deeper:
input_data = {
"foo": "bar",
"x": "y",
"Something": 12345,
"other": [
{
"yes": 1,
"no": 0
}
],
}
If I were to convert this data, I would expect the resulting object to be used like so:
>>> converted_data = DataConverter(input_data)
>>> converted_data.other[0].yes
1
This issue occurs when I get data structured like so:
input_data = [
{
"foo": "bar",
},
{
"x": "y",
},
{
"Something": 12345,
},
{
"other": [
{
"yes": 1,
"no": 0
}
]
}
]
and I would expect this data to be used like so after conversion:
>>> converted_data = DataConverter(input_data)
>>> converted_data[3].other[0].no
0
I began writing something I imagined would work, but I can't figure out how to have the DataConverter object init as a list object if the input is a list.
Answer
Based on JL Peyret's answer, I have added the factory method and changed a bit of code to make a better version.
class DataConverter(object):
def __init__(self, input_data):
if isinstance(input_data, dict):
for key, data in input_data.items():
if isinstance(data, dict):
setattr(self, key, DataConverter(data))
elif isinstance(data, list):
setattr(self, key, DataConverter.factory(data))
else:
setattr(self, key, data)
@classmethod
def factory(cls, data_input):
if isinstance(data_input, dict):
return DataConverter(data_input)
elif isinstance(data_input, list):
package = []
for part in package:
package.append(cls.factory(part))
return package
The intended use is now
>>> obj = DataConverter.factory(input_data)
>>> obj[3].other[0].yes
1