This is a form Template sample:

{
    "form": "inventoryForm",
    "name": "inventoryForm",
    "fields": [
        {
            "name": "transactionInfo",
            "type": "Section",
            "fields": [
                {
                    "name": "transaction",
                    "type": "SelectOne",
                    "listName": "transactionTypes"
                },
                {
                    "name": "supplier",
                    "type": "Text",
                    "rules": [
                        {
                            "expression": "#{transaction} == 'supply'",
                            "action": "Show"
                        }
                    ]
                }
            ]
        }
    ]
}

It's stored in mongo db connected to using spring boot, I fetch into a flutter app, serialize in model mirroring this json structure, and store form in a sqlite db with its children stored as a json in one field from which i deserializes the fields when fetching from the sqlite to parse the widgets that represent each field:

class FormTemplateV extends IdentifiableEntity {
  @ManyToOne(table: FormTemplate, joinColumnName: 'formTemplate')
  dynamic formTemplate;

  @Column(nullable: true, type: ColumnType.TEXT)
  List<FormElementTemplate> fields = [];

  @Column(nullable: true, type: ColumnType.TEXT)
  List<DOptionSet> optionSets = [];
//..fromJson, toJson... and other code
}

class FormElementTemplate with EquatableMixin {
  final ValueType type;
  final String name;
  final int order;
  final String? fieldValueRenderingType;
  final Map<String, String> label = {};
  final List<Rule> rules = [];
}

class FieldTemplate extends FormElementTemplate with ElementAttributesMixin {
  final String? listName;
  final String? choiceFilter;
  final dynamic defaultValue;
//..fromJson, toJson... and other code
}

/// represent a Section or RepeatableSection, the ValueType tell which on it is
class SectionTemplate extends FormElementTemplate {
  final List<FormElementTemplate> fields = [];

  //..fromJson, toJson... and other code
}

Serializing and deserializing:

FormElementTemplate fromJsonFactory(Map<String, dynamic> json) {
  final type = json['type'] as String?;
  final valueType = ValueType.getValueType(type);

  switch (valueType) {
    case ValueType.Section:
    case ValueType.RepeatableSection:
      return SectionTemplate.fromJson(json);
    default:
      return FieldTemplate.fromJson(json);
  }
}

Map<String, dynamic> toJsonFactory(FormElementTemplate field) {
  switch (field.type) {
    case ValueType.Section:
    case ValueType.RepeatableSection:
      return (field as SectionTemplate).toJson();
    default:
      return (field as FieldTemplate).toJson();
  }
}