createSerializer method

Mapper createSerializer()

Implementation

Mapper createSerializer() {
  Map<Type, MappingDefinition> mappings = {};
  var queue = Queue<Type>.from([type]);

  // local function

  void check(Type type) {
    if ( !TypeDescriptor.hasType(type))
      return;

    // own class

    if (!mappings.containsKey(type)) {
      queue.add(type);

      // check subclasses as well

      for ( var sub in TypeDescriptor.forType(type).childClasses)
        check(sub.type);
    }
  }

  MappingDefinition process(Type type) {
    var typeMapping = MappingDefinition<dynamic,Map<String, dynamic>>(sourceClass: type, targetClass: Map<String, dynamic>);
    var typeDescriptor = TypeDescriptor.forType(type);

    var jsonSerializable = typeDescriptor.findAnnotation<JsonSerializable>() ?? JsonSerializable();

    mappings[type] = typeMapping;

    // process fields

    for (var field in typeDescriptor.getFields()) {
      var json = field.findAnnotation<Json>() ?? Json(name: field.name, defaultValue: null);
      var includeNull = jsonSerializable.includeNull && json.includeNull != false;

      if ( json.ignore)
        continue;

      var jsonField = json.name;
      if (jsonField.isEmpty)
        jsonField = field.name;

      if (field.type is ListType) {
        var elementType = field.elementType;

        check(elementType!);

        typeMapping.map(
            from: field.name,
            to: JSONAccessor(
                name: jsonField,
                type: Map<String, dynamic>,
                includeNull: includeNull,
                containerConstructor: () => []
            ),
            deep: true
        ); // index?
      }
      else if ( field.type is ObjectType) {
        var objectType = field.type as ObjectType;

        if ( objectType.typeDescriptor.isEnum()) {
          Convert? convertSource = JSON.instance.getConvert(field.type.type);

          typeMapping.map(
              from: field.name,
              to: JSONAccessor(
                  name: jsonField,
                  type: field.type.type,
                  convert: convertSource?.sourceConverter(),
                  includeNull: includeNull
              )
          );
        }
        else {
          var target = objectType.type;

          // manual converter?

          Convert? convert ;
          if ( json.converter != null) {
            convert = JSON.getConvert4(json.converter!);
          }
          else convert = JSON.instance.getConvert(field.type.type);

          if ( convert == null)
            check(target);

          typeMapping.map(
              convert: convert,
              from: field.name,
              to: JSONAccessor(
                  name: jsonField,
                  type: Map<String, dynamic>,
                  includeNull: includeNull,
                  //convert: convert?.sourceConverter()
              ),
              deep: convert == null,
              validate: validate
          ); // index?
        }
      } // if
      else {
        Convert? convert ;
        if ( json.converter != null) {
          convert = JSON.getConvert4(json.converter!);
        }
        else convert = JSON.instance.getConvert(field.type.type);

        typeMapping.map(
            from: field.name,
            to: JSONAccessor(
                name: jsonField,
                type: field.type.type,
                convert: convert?.sourceConverter(),
                includeNull: includeNull
            ),
            validate: validate
        );
      }
    }

    return typeMapping;
  }

  // work on queue

  while (queue.isNotEmpty) {
    process(queue.removeFirst());
  }

  // done

  var mapper = Mapper(mappings.values.toList());

  serializerMapping = mapper.getMappingX(type, Map<String,dynamic>);

  return mapper;
}