fromJson static method
Parses a carousel templateConfig object. Returns null when the config
is missing a slotKey or has no valid items — mirroring Android, where
such campaigns are dropped rather than rendered empty.
Implementation
static InlineCarouselConfig? fromJson(Map<String, dynamic> json) {
final slotKey = optString(json, 'slotKey');
if (slotKey.isEmpty) return null;
final itemsArr = optList(json, 'items');
if (itemsArr == null) return null;
final items = <CarouselItem>[];
for (final raw in itemsArr) {
if (raw is! Map) continue;
final itemJson = raw.cast<String, dynamic>();
final imageUrl = optString(itemJson, 'imageUrl');
if (imageUrl.isEmpty) continue;
final deepLink = optString(itemJson, 'deepLink');
final onClick = optMap(itemJson, 'onClick');
final fit = switch (optString(itemJson, 'fit', 'cover')) {
'contain' => CarouselItemFit.contain,
'fill' => CarouselItemFit.fill,
_ => CarouselItemFit.cover,
};
items.add(
CarouselItem(
imageUrl: imageUrl,
actions: onClick != null
? const EngageActionParser().parse(onClick)
: deepLink.isEmpty
? const []
: [OpenDeeplinkAction(deepLink)],
fit: fit,
placeholder: ImagePlaceholder.fromJson(
optMap(itemJson, 'placeholder'),
),
),
);
}
if (items.isEmpty) return null;
final rawAspectRatio = optDouble(json, 'aspectRatio', 0);
final aspectRatio =
rawAspectRatio.isFinite && rawAspectRatio > 0 ? rawAspectRatio : 0.0;
return InlineCarouselConfig(
slotKey: slotKey,
items: items,
aspectRatio: aspectRatio,
height: optPositiveInt(json, 'height', 180),
autoPlay: optBool(json, 'autoPlay', true),
autoPlayInterval: optInt(json, 'autoPlayInterval', 3000),
animationDuration: optInt(json, 'animationDuration', 700),
infiniteScroll: optBool(json, 'infiniteScroll', true),
viewportFraction: optDouble(json, 'viewportFraction', 0.88),
itemSpacing: optDouble(json, 'itemSpacing', 12),
cornerRadius: optDouble(json, 'cornerRadius', 12),
indicator: CarouselIndicatorConfig.fromJson(optMap(json, 'indicator')),
);
}