fromDynamic static method

JsonWidgetData? fromDynamic(
  1. dynamic map, {
  2. JsonWidgetRegistry? registry,
})

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