arrayNode<T> method

JsonArray<List<T>> arrayNode<T>(
  1. String key, {
  2. T decodeFromJsonObject(
    1. JsonObject
    )?,
  3. Function? decoder,
  4. List? childType,
})

Get JsonArray by String key.

Throws SquintException if key is not found.

Implementation

JsonArray<List<T>> arrayNode<T>(
  String key, {
  T Function(JsonObject)? decodeFromJsonObject,
  Function? decoder,
  List? childType,
}) {
  final dynamicData = byKey(key).data as List;
  final expectedChildType = T.toString();
  final actualChildType = dynamicData.runtimeType
      .toString()
      .removePrefixIfPresent("List<")
      .removePostfixIfPresent(">");

  // Types match so cast and return List<T>.
  if (expectedChildType == actualChildType) {
    return JsonArray<List<T>>(
      key: key,
      data: dynamicData.cast<T>().toList(),
    );
  }

  // Use decoder to convert to expected child Type
  // and return as List<T>.
  if (decodeFromJsonObject != null) {
    final objects = dynamicData.map<JsonObject>((dynamic e) {
      if (e is Map) {
        if (e.values.isNotEmpty && e.values.first is JsonNode) {
          return JsonObject(data: e as Map<String, JsonNode>);
        } else {
          return JsonObject.fromMap(data: e as Map<String, dynamic>);
        }
      } else {
        throw SquintException(
            "Expected Map type but found: ${e.runtimeType}");
      }
    }).toList();
    return JsonArray<List<T>>(
      key: key,
      data: objects.map(decodeFromJsonObject).toList().cast<T>().toList(),
    );
  }

  var depth = 0;
  var nextChild = actualChildType;
  while (nextChild.startsWith("List<")) {
    nextChild =
        nextChild.removePrefixIfPresent("List<").removePostfixIfPresent(">");
    depth += 1;
  }

  final isMapType = mapRegex.firstMatch(nextChild);
  if (isMapType != null) {
    if (depth == 0) {
      final objects = dynamicData.map<JsonObject>((dynamic e) {
        if (e is Map) {
          if (e.values.isNotEmpty && e.values.first is JsonNode) {
            return JsonObject(data: e as Map<String, JsonNode>);
          } else {
            return JsonObject.fromMap(data: e as Map<String, dynamic>);
          }
        } else {
          throw SquintException(
              "Expected Map type but found: ${e.runtimeType}");
        }
      }).toList();
      final maps = objects.map<dynamic>((e) {
        final type = e.valuesAllOfSameType;
        if (type is StringType) {
          final stringMap = <String, String>{};
          e.data.forEach((key, value) {
            stringMap[key] = value.data as String;
          });
          return stringMap;
        } else if (type is IntType) {
          final intMap = <String, int>{};
          e.data.forEach((key, value) {
            intMap[key] = value.data as int;
          });
          return intMap;
        } else if (type is DoubleType) {
          final doubleMap = <String, double>{};
          e.data.forEach((key, value) {
            doubleMap[key] = value.data as double;
          });
          return doubleMap;
        } else if (type is BooleanType) {
          final boolMap = <String, bool>{};
          e.data.forEach((key, value) {
            boolMap[key] = value.data as bool;
          });
          return boolMap;
        } else {
          if (decoder != null) {
            try {
              return decoder.call(e);
            } catch (e) {
              "Tried to decode data with $decoder but failed."
                  .log(context: e);
            }
          }

          return e.data;
        }
      }).toList();
      return JsonArray<List<T>>(
        key: key,
        data: maps.toList().cast<T>().toList(),
      );
    }
  }

  final nodes = dynamicData.decodeList;
  final decoded = <String, JsonNode>{};

  if (decoder != null) {
    try {
      nodes.forEach((key, value) {
        decoded[key] = CustomJsonNode(data: decoder.call(value));
      });
    } catch (e) {
      "Decoding failed due to:".log(context: e);
      throw SquintException("Tried to decode data with $decoder but failed.");
    }
  }

  if (decoded.isNotEmpty) {
    final decodedList = decoded.toList(valueList: childType);
    return JsonArray<List<T>>(
      key: key,
      data: decodedList.cast<T>(),
    );
  }

  // Return as List with child T.
  return JsonArray<List<T>>(
    key: key,
    data: nodes.toList().cast<T>().toList(),
  );
}