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