deserialize method
Transforms JSON:API into native format (with included resources)
Implementation
@override
Future<DeserializedData<T>> deserialize(Object? data, {String? key}) async {
final result = DeserializedData<T>([], included: []);
final collection = ResourceCollection();
if (data is! Iterable<Resource>) {
// if data is not already formatted, parse
try {
final inbound = InboundDocument(data as Map);
final isSingle = inbound.json['data'] is Map;
if (isSingle) {
collection.add(inbound.dataAsResource());
} else {
collection.addAll(inbound.dataAsCollection());
}
// group by type
final grouped = groupBy<Resource, String>(
inbound.included(), (r) => _internalTypeFor(r.type));
for (final e in grouped.entries) {
final internalType = e.key;
if (adapters.containsKey(internalType)) {
final data = await adapters[internalType]!.deserialize(e.value);
result.included
.addAll(List<DataModel<DataModel>>.from(data.models));
}
}
} catch (err, stack) {
throw DataException('Invalid JSON:API, $err', stackTrace: stack);
}
} else {
// if data was already formatted, add to collection
collection.addAll(data);
}
// process resources in collection
for (final resource in collection) {
final mapOut = <String, dynamic>{};
mapOut['id'] = resource.id;
for (final relEntry in (resource.relationships).entries) {
final rel = relEntry.value;
final mapOutKey = relEntry.key;
if (rel is ToOne && rel.identifier != null) {
final key = rel.identifier!.id;
mapOut[mapOutKey] = key;
}
if (rel is ToMany) {
mapOut[mapOutKey] = rel.map((i) {
return i.id;
}).toList();
}
}
for (final attrEntry in resource.attributes.entries) {
mapOut[attrEntry.key] = attrEntry.value;
}
final data = await super.deserialize(mapOut);
result.models.addAll(data.models);
}
return result;
}