deserialize method

  1. @override
Future<DeserializedData<T>> deserialize(
  1. Object? data, {
  2. String? key,
})

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;
}