fromDynamic static method
Decodes a JSON object into a dynamic widget. The structure is the same
for all dynamic widgets with the exception of the args value. The
args depends on the specific type.
In the given JSON object, only the child or the children can be passed
in; not both. From an implementation perspective, there is no difference
between passing in a child or a children with a single element, this
will treat both of those identically.
{ "type":
Implementation
static JsonWidgetData? fromDynamic(
dynamic map, {
JsonWidgetRegistry? registry,
}) {
JsonWidgetData? result;
registry ??= JsonWidgetRegistry.instance;
if (map is String && map.startsWith('{') && map.endsWith('}')) {
try {
map = json.decode(map);
} catch (e) {
// no-op; it probably just isn't a JSON string
}
}
if (map is JsonWidgetData) {
result = map;
} else if (map is String && map.startsWith('\${') && map.endsWith('}')) {
result = DeferredJsonWidgetData(
key: map,
registry: registry,
);
} else if (map != null) {
try {
var type = map['type'];
if (type is! String) {
throw HandledJsonWidgetException(
'Unknown type encountered: [$type]',
null,
data: map,
);
}
var builder = registry.getWidgetBuilder(type);
var args = map['args'];
var listenVariables = _getListenVariables(map);
// The validation needs to happen before we process the dynamic args or
// else there may be non-JSON compatible objects in the map which will
// always fail validation.
assert(registry.validateBuilderSchema(
type: type,
value: args,
validate: args == null ? false : true,
));
var child = JsonWidgetData.fromDynamic(
map['child'],
registry: registry,
);
if (type == 'scaffold' && map['args'] is Map && child == null) {
child = JsonWidgetData.fromDynamic(
map['args']['body'],
registry: registry,
);
var args = Map<String, dynamic>.from(map['args']);
args.remove('body');
map['args'] = args;
}
var processedArgs =
registry.processArgs(args ?? <String, dynamic>{}, listenVariables);
result = JsonWidgetData(
args: map['args'] ?? {},
builder: () {
return builder(
registry!
.processArgs(args ?? <String, dynamic>{}, listenVariables)
.value,
registry: registry,
)!;
},
child: child,
children: map['children'] is String
? registry.processArgs(map['children'], listenVariables).value
: JsonClass.fromDynamicList(
map['children'],
(dynamic map) => JsonWidgetData.fromDynamic(
map,
registry: registry,
)!,
),
listenVariables: processedArgs.listenVariables,
id: map['id'],
originalChild: map['child'],
originalChildren: map['children'],
registry: registry,
type: type,
);
} catch (e, stack) {
if (e is HandledJsonWidgetException) {
rethrow;
}
var errorValue = map;
if (errorValue is Map || errorValue is List) {
errorValue = JsonEncoder.withIndent(' ').convert(errorValue);
}
_logger.severe('''
*** WIDGET PARSE ERROR ***
$errorValue
$map
''', e, stack);
throw HandledJsonWidgetException(
e,
stack,
data: errorValue,
);
}
}
return result;
}