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