protected generateSerializationMethod()

in packages/appsync-modelgen-plugin/src/visitors/appsync-dart-visitor.ts [540:693]


  protected generateSerializationMethod(model: CodeGenModel, declarationBlock: DartDeclarationBlock): void {
    //serialization: Model.fromJson
    const serializationImpl = `\n: ${indentMultiline(
      model.fields
        .map(field => {
          const varName = this.getFieldName(field);
          const fieldName = `${this.isNullSafety() && field.name !== 'id' ? '_' : ''}${this.getFieldName(field)}`;
          //model type
          if (this.isModelType(field)) {
            if (field.isList) {
              return [
                `${fieldName} = json['${varName}'] is List`,
                indent(`? (json['${varName}'] as List)`),
                this.isNullSafety() ? indent(`.where((e) => e?['serializedData'] != null)`, 2) : undefined,
                indent(
                  `.map((e) => ${this.getNativeType({ ...field, isList: false })}.fromJson(new Map<String, dynamic>.from(e${
                    this.isNullSafety() ? `['serializedData']` : ''
                  })))`,
                  2,
                ),
                indent(`.toList()`, 2),
                indent(`: null`),
              ]
                .filter(e => e !== undefined)
                .join('\n');
            }
            return [
              `${fieldName} = json['${varName}']${this.isNullSafety() ? `?['serializedData']` : ''} != null`,
              indent(
                `? ${this.getNativeType(field)}.fromJson(new Map<String, dynamic>.from(json['${varName}']${
                  this.isNullSafety() ? `['serializedData']` : ''
                }))`,
              ),
              indent(`: null`),
            ].join('\n');
          }
          //enum type
          if (this.isEnumType(field)) {
            if (field.isList) {
              return [
                `${fieldName} = json['${varName}'] is List`,
                indent(`? (json['${varName}'] as List)`),
                indent(`.map((e) => enumFromString<${field.type}>(e, ${field.type}.values)${this.isNullSafety() ? '!' : ''})`, 2),
                indent(`.toList()`, 2),
                indent(`: null`),
              ].join('\n');
            }
            return `${fieldName} = enumFromString<${field.type}>(json['${varName}'], ${field.type}.values)`;
          }
          // embedded, embeddedCollection of non-model
          if (this.isNonModelType(field)) {
            // list of non-model i.e. embeddedCollection
            if (field.isList) {
              return [
                `${fieldName} = json['${varName}'] is List`,
                indent(`? (json['${varName}'] as List)`),
                this.isNullSafety() ? indent(`.where((e) => e != null)`, 2) : undefined,
                indent(
                  `.map((e) => ${this.getNativeType({ ...field, isList: false })}.fromJson(new Map<String, dynamic>.from(${this.isNonModelType(field) ? 'e[\'serializedData\']' : 'e'})))`,
                  2,
                ),
                indent(`.toList()`, 2),
                indent(`: null`),
              ].filter((e) => e !== undefined).join('\n');
            }
            // single non-model i.e. embedded
            return [
              `${fieldName} = json['${varName}']${this.isNullSafety() ? `?['serializedData']`:''} != null`,
              indent(
                `? ${this.getNativeType(field)}.fromJson(new Map<String, dynamic>.from(json['${varName}']${
                  this.isNullSafety() ? `['serializedData']` : ''
                }))`,
              ),
              indent(`: null`),
            ].join('\n');
          }
          //regular type
          const fieldNativeType = this.getNativeType({ ...field, isList: false });
          switch (fieldNativeType) {
            case this.scalars['AWSDate']:
            case this.scalars['AWSTime']:
            case this.scalars['AWSDateTime']:
              return field.isList
                ? `${fieldName} = (json['${varName}'] as ${this.getNullSafetyTypeStr(
                    'List',
                  )})?.map((e) => ${fieldNativeType}.fromString(e)).toList()`
                : `${fieldName} = json['${varName}'] != null ? ${fieldNativeType}.fromString(json['${varName}']) : null`;
            case this.scalars['AWSTimestamp']:
              return field.isList
                ? `${fieldName} = (json['${varName}'] as ${this.getNullSafetyTypeStr(
                    'List',
                  )})?.map((e) => ${fieldNativeType}.fromSeconds(e)).toList()`
                : `${fieldName} = json['${varName}'] != null ? ${fieldNativeType}.fromSeconds(json['${varName}']) : null`;
            case this.scalars['Int']:
              return field.isList
                ? `${fieldName} = (json['${varName}'] as ${this.getNullSafetyTypeStr('List')})?.map((e) => (e as num).toInt()).toList()`
                : `${fieldName} = (json['${varName}'] as ${this.getNullSafetyTypeStr('num')})?.toInt()`;
            case this.scalars['Float']:
              return field.isList
                ? `${fieldName} = (json['${varName}'] as ${this.getNullSafetyTypeStr('List')})?.map((e) => (e as num).toDouble()).toList()`
                : `${fieldName} = (json['${varName}'] as ${this.getNullSafetyTypeStr('num')})?.toDouble()`;
            default:
              return field.isList
                ? `${fieldName} = json['${varName}']?.cast<${this.getNativeType({ ...field, isList: false })}>()`
                : `${fieldName} = json['${varName}']`;
          }
        })
        .join(',\n'),
    ).trim()};`;
    declarationBlock.addClassMethod(
      `${this.getModelName(model)}.fromJson`,
      ``,
      [{ name: 'json', type: 'Map<String, dynamic>' }],
      indentMultiline(serializationImpl),
      { isBlock: false },
    );
    //deserialization: toJson
    const toJsonFields = model.fields
      .map(field => {
        const varName = this.getFieldName(field);
        const fieldName = `${this.isNullSafety() && field.name !== 'id' ? '_' : ''}${this.getFieldName(field)}`;
        if (this.isModelType(field) || this.isNonModelType(field)) {
          if (field.isList) {
            const modelName = this.getNativeType({ ...field, isList: false });
            return this.isNullSafety()
              ? `'${varName}': ${fieldName}?.map((${modelName}? e) => e?.toJson()).toList()`
              : `'${varName}': ${fieldName}?.map((${modelName} e) => e?.toJson())?.toList()`;
          }
          return `'${varName}': ${fieldName}?.toJson()`;
        }
        if (this.isEnumType(field)) {
          if (field.isList) {
            return `'${varName}': ${fieldName}?.map((e) => enumToString(e)).toList()`;
          }
          return `'${varName}': enumToString(${fieldName})`;
        }
        const fieldNativeType = this.getNativeType({ ...field, isList: false });
        switch (fieldNativeType) {
          case this.scalars['AWSDate']:
          case this.scalars['AWSTime']:
          case this.scalars['AWSDateTime']:
            return field.isList ? `'${varName}': ${fieldName}?.map((e) => e.format()).toList()` : `'${varName}': ${fieldName}?.format()`;
          case this.scalars['AWSTimestamp']:
            return field.isList
              ? `'${varName}': ${fieldName}?.map((e) => e.toSeconds()).toList()`
              : `'${varName}': ${fieldName}?.toSeconds()`;
          default:
            return `'${varName}': ${fieldName}`;
        }
      })
      .join(', ');
    const deserializationImpl = [' => {', indentMultiline(toJsonFields), '};'].join('\n');
    declarationBlock.addClassMethod('toJson', 'Map<String, dynamic>', [], deserializationImpl, { isBlock: false });
  }