mirror of
https://github.com/immich-app/immich
synced 2026-08-15 13:03:57 +00:00
chore(mobile): harden mobile OpenAPI codegen and dependency install (#30202)
* chore(mobile): harden mobile OpenAPI codegen and dependency install * Cleaner mise cascade * Version openapi-generator-cli with mise * Relocate tool definition * Update lock file
This commit is contained in:
parent
3606144190
commit
e3385ce183
11 changed files with 55 additions and 755 deletions
|
|
@ -1,22 +1,19 @@
|
|||
#!/usr/bin/env bash
|
||||
OPENAPI_GENERATOR_VERSION=v7.24.0
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# usage: ./bin/generate-dart-sdk.sh
|
||||
|
||||
TEMPLATE_DIR=$(mktemp -d)
|
||||
trap 'rm -rf "$TEMPLATE_DIR"' EXIT
|
||||
|
||||
# Installed via mise
|
||||
openapi-generator-cli author template -g dart -o "$TEMPLATE_DIR"
|
||||
patch --no-backup-if-mismatch -u "$TEMPLATE_DIR/api.mustache" <./templates/mobile/api.mustache.patch
|
||||
patch --no-backup-if-mismatch -u "$TEMPLATE_DIR/serialization/native/native_class.mustache" <./templates/mobile/serialization/native/native_class.mustache.patch
|
||||
|
||||
rm -rf ../mobile/openapi
|
||||
|
||||
cd ./templates/mobile/serialization/native
|
||||
wget -O native_class.mustache https://raw.githubusercontent.com/OpenAPITools/openapi-generator/$OPENAPI_GENERATOR_VERSION/modules/openapi-generator/src/main/resources/dart2/serialization/native/native_class.mustache
|
||||
patch --no-backup-if-mismatch -u native_class.mustache <native_class.mustache.patch
|
||||
|
||||
cd ../../
|
||||
wget -O api.mustache https://raw.githubusercontent.com/OpenAPITools/openapi-generator/$OPENAPI_GENERATOR_VERSION/modules/openapi-generator/src/main/resources/dart2/api.mustache
|
||||
patch --no-backup-if-mismatch -u api.mustache <api.mustache.patch
|
||||
|
||||
cd ../../
|
||||
pnpm dlx --allow-build="" @openapitools/openapi-generator-cli generate -g dart -i ./immich-openapi-specs.json -o ../mobile/openapi -t ./templates/mobile --additional-properties=useOptional=true
|
||||
openapi-generator-cli generate -g dart -i ./immich-openapi-specs.json -o ../mobile/openapi -t "$TEMPLATE_DIR" --additional-properties=useOptional=true
|
||||
|
||||
# Post generate patches
|
||||
patch --no-backup-if-mismatch -u ../mobile/openapi/lib/api_client.dart <./patch/api_client.dart.patch
|
||||
|
|
|
|||
|
|
@ -1,196 +0,0 @@
|
|||
{{>header}}
|
||||
{{>part_of}}
|
||||
|
||||
{{#operations}}
|
||||
|
||||
class {{{classname}}} {
|
||||
{{{classname}}}([ApiClient? apiClient]) : apiClient = apiClient ?? defaultApiClient;
|
||||
|
||||
final ApiClient apiClient;
|
||||
{{#operation}}
|
||||
|
||||
{{#summary}}
|
||||
/// {{{.}}}
|
||||
{{/summary}}
|
||||
{{#notes}}
|
||||
{{#summary}}
|
||||
///
|
||||
{{/summary}}
|
||||
/// {{{notes}}}
|
||||
///
|
||||
/// Note: This method returns the HTTP [Response].
|
||||
{{/notes}}
|
||||
{{^notes}}
|
||||
{{#summary}}
|
||||
///
|
||||
/// Note: This method returns the HTTP [Response].
|
||||
{{/summary}}
|
||||
{{^summary}}
|
||||
/// Performs an HTTP '{{{httpMethod}}} {{{path}}}' operation and returns the [Response].
|
||||
{{/summary}}
|
||||
{{/notes}}
|
||||
{{#hasParams}}
|
||||
{{#summary}}
|
||||
///
|
||||
{{/summary}}
|
||||
{{^summary}}
|
||||
{{#notes}}
|
||||
///
|
||||
{{/notes}}
|
||||
{{/summary}}
|
||||
/// Parameters:
|
||||
///
|
||||
{{/hasParams}}
|
||||
{{#allParams}}
|
||||
/// * [{{{dataType}}}] {{{paramName}}}{{#required}} (required){{/required}}{{#optional}} (optional){{/optional}}:
|
||||
{{#description}}
|
||||
/// {{{.}}}
|
||||
{{/description}}
|
||||
{{^-last}}
|
||||
///
|
||||
{{/-last}}
|
||||
{{/allParams}}
|
||||
Future<Response> {{{nickname}}}WithHttpInfo({{#allParams}}{{#required}}{{{dataType}}} {{{paramName}}}, {{/required}}{{/allParams}}{ {{#allParams}}{{^required}}{{{dataType}}}? {{{paramName}}}, {{/required}}{{/allParams}}Future<void>? abortTrigger, }) async {
|
||||
// ignore: prefer_const_declarations
|
||||
final apiPath = r'{{{path}}}'{{#pathParams}}
|
||||
.replaceAll({{=<% %>=}}'{<% baseName %>}'<%={{ }}=%>, {{{paramName}}}{{^isString}}.toString(){{/isString}}){{/pathParams}};
|
||||
|
||||
// ignore: prefer_final_locals
|
||||
Object? postBody{{#bodyParam}} = {{{paramName}}}{{/bodyParam}};
|
||||
|
||||
final queryParams = <QueryParam>[];
|
||||
final headerParams = <String, String>{};
|
||||
final formParams = <String, String>{};
|
||||
{{#hasQueryParams}}
|
||||
|
||||
{{#queryParams}}
|
||||
{{^required}}
|
||||
if ({{{paramName}}} != null) {
|
||||
{{/required}}
|
||||
queryParams.addAll(_queryParams('{{{collectionFormat}}}', '{{{baseName}}}', {{{paramName}}}));
|
||||
{{^required}}
|
||||
}
|
||||
{{/required}}
|
||||
{{/queryParams}}
|
||||
{{/hasQueryParams}}
|
||||
{{#hasHeaderParams}}
|
||||
|
||||
{{#headerParams}}
|
||||
{{#required}}
|
||||
headerParams[r'{{{baseName}}}'] = parameterToString({{{paramName}}});
|
||||
{{/required}}
|
||||
{{^required}}
|
||||
if ({{{paramName}}} != null) {
|
||||
headerParams[r'{{{baseName}}}'] = parameterToString({{{paramName}}});
|
||||
}
|
||||
{{/required}}
|
||||
{{/headerParams}}
|
||||
{{/hasHeaderParams}}
|
||||
|
||||
const contentTypes = <String>[{{#prioritizedContentTypes}}'{{{mediaType}}}'{{^-last}}, {{/-last}}{{/prioritizedContentTypes}}];
|
||||
|
||||
{{#isMultipart}}
|
||||
bool hasFields = false;
|
||||
final mp = MultipartRequest('{{{httpMethod}}}', Uri.parse(apiPath));
|
||||
{{#formParams}}
|
||||
{{^isFile}}
|
||||
if ({{{paramName}}} != null) {
|
||||
hasFields = true;
|
||||
mp.fields[r'{{{baseName}}}'] = parameterToString({{{paramName}}});
|
||||
}
|
||||
{{/isFile}}
|
||||
{{#isFile}}
|
||||
if ({{{paramName}}} != null) {
|
||||
hasFields = true;
|
||||
mp.fields[r'{{{baseName}}}'] = {{{paramName}}}.field;
|
||||
mp.files.add({{{paramName}}});
|
||||
}
|
||||
{{/isFile}}
|
||||
{{/formParams}}
|
||||
if (hasFields) {
|
||||
postBody = mp;
|
||||
}
|
||||
{{/isMultipart}}
|
||||
{{^isMultipart}}
|
||||
{{#formParams}}
|
||||
{{^isFile}}
|
||||
if ({{{paramName}}} != null) {
|
||||
formParams[r'{{{baseName}}}'] = parameterToString({{{paramName}}});
|
||||
}
|
||||
{{/isFile}}
|
||||
{{/formParams}}
|
||||
{{/isMultipart}}
|
||||
|
||||
return apiClient.invokeAPI(
|
||||
apiPath,
|
||||
'{{{httpMethod}}}',
|
||||
queryParams,
|
||||
postBody,
|
||||
headerParams,
|
||||
formParams,
|
||||
contentTypes.isEmpty ? null : contentTypes.first,
|
||||
abortTrigger: abortTrigger,
|
||||
);
|
||||
}
|
||||
|
||||
{{#summary}}
|
||||
/// {{{.}}}
|
||||
{{/summary}}
|
||||
{{#notes}}
|
||||
{{#summary}}
|
||||
///
|
||||
{{/summary}}
|
||||
/// {{{notes}}}
|
||||
{{/notes}}
|
||||
{{#hasParams}}
|
||||
{{#summary}}
|
||||
///
|
||||
{{/summary}}
|
||||
{{^summary}}
|
||||
{{#notes}}
|
||||
///
|
||||
{{/notes}}
|
||||
{{/summary}}
|
||||
/// Parameters:
|
||||
///
|
||||
{{/hasParams}}
|
||||
{{#allParams}}
|
||||
/// * [{{{dataType}}}] {{{paramName}}}{{#required}} (required){{/required}}{{#optional}} (optional){{/optional}}:
|
||||
{{#description}}
|
||||
/// {{{.}}}
|
||||
{{/description}}
|
||||
{{^-last}}
|
||||
///
|
||||
{{/-last}}
|
||||
{{/allParams}}
|
||||
Future<{{#returnType}}{{{.}}}?{{/returnType}}{{^returnType}}void{{/returnType}}> {{{nickname}}}({{#allParams}}{{#required}}{{{dataType}}} {{{paramName}}}, {{/required}}{{/allParams}}{ {{#allParams}}{{^required}}{{{dataType}}}? {{{paramName}}}, {{/required}}{{/allParams}}Future<void>? abortTrigger, }) async {
|
||||
final response = await {{{nickname}}}WithHttpInfo({{#allParams}}{{#required}}{{{paramName}}}, {{/required}}{{/allParams}}{{#allParams}}{{^required}}{{{paramName}}}: {{{paramName}}}, {{/required}}{{/allParams}}abortTrigger: abortTrigger,);
|
||||
if (response.statusCode >= HttpStatus.badRequest) {
|
||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||
}
|
||||
{{#returnType}}
|
||||
// When a remote server returns no body with a status of 204, we shall not decode it.
|
||||
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
||||
// FormatException when trying to decode an empty string.
|
||||
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
||||
{{#native_serialization}}
|
||||
{{#isArray}}
|
||||
final responseBody = await _decodeBodyBytes(response);
|
||||
return (await apiClient.deserializeAsync(responseBody, '{{{returnType}}}') as List)
|
||||
.cast<{{{returnBaseType}}}>()
|
||||
.{{#uniqueItems}}toSet(){{/uniqueItems}}{{^uniqueItems}}toList(growable: false){{/uniqueItems}};
|
||||
{{/isArray}}
|
||||
{{^isArray}}
|
||||
{{#isMap}}
|
||||
return {{{returnType}}}.from(await apiClient.deserializeAsync(await _decodeBodyBytes(response), '{{{returnType}}}'),);
|
||||
{{/isMap}}
|
||||
{{^isMap}}
|
||||
return await apiClient.deserializeAsync(await _decodeBodyBytes(response), '{{{returnType}}}',) as {{{returnType}}};
|
||||
{{/isMap}}{{/isArray}}{{/native_serialization}}
|
||||
}
|
||||
return null;
|
||||
{{/returnType}}
|
||||
}
|
||||
{{/operation}}
|
||||
}
|
||||
{{/operations}}
|
||||
|
|
@ -1,458 +0,0 @@
|
|||
class {{{classname}}} {
|
||||
{{>dart_constructor}}
|
||||
|
||||
{{#vars}}
|
||||
{{#description}}
|
||||
/// {{{.}}}
|
||||
{{/description}}
|
||||
{{^isEnum}}
|
||||
{{#minimum}}
|
||||
{{#description}}
|
||||
///
|
||||
{{/description}}
|
||||
/// Minimum value: {{{.}}}
|
||||
{{/minimum}}
|
||||
{{#maximum}}
|
||||
{{#description}}
|
||||
{{^minimum}}
|
||||
///
|
||||
{{/minimum}}
|
||||
{{/description}}
|
||||
/// Maximum value: {{{.}}}
|
||||
{{/maximum}}
|
||||
{{^isNullable}}
|
||||
{{^required}}
|
||||
{{^defaultValue}}
|
||||
///
|
||||
/// Please note: This property should have been non-nullable! Since the specification file
|
||||
/// does not include a default value (using the "default:" property), however, the generated
|
||||
/// source code must fall back to having a nullable type.
|
||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||
///
|
||||
{{/defaultValue}}
|
||||
{{/required}}
|
||||
{{/isNullable}}
|
||||
{{/isEnum}}
|
||||
{{#required}}
|
||||
{{#useFinalProperties}}final {{/useFinalProperties}}{{{datatypeWithEnum}}}{{#isNullable}}?{{/isNullable}} {{{name}}};
|
||||
{{/required}}
|
||||
{{^required}}
|
||||
{{#vendorExtensions.x-is-optional}}
|
||||
{{#useFinalProperties}}final {{/useFinalProperties}}{{{datatypeWithEnum}}} {{{name}}};
|
||||
{{/vendorExtensions.x-is-optional}}
|
||||
{{^vendorExtensions.x-is-optional}}
|
||||
{{#useFinalProperties}}final {{/useFinalProperties}}{{{datatypeWithEnum}}}{{#isNullable}}?{{/isNullable}}{{^isNullable}}{{^defaultValue}}?{{/defaultValue}}{{/isNullable}} {{{name}}};
|
||||
{{/vendorExtensions.x-is-optional}}
|
||||
{{/required}}
|
||||
|
||||
{{/vars}}
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is {{{classname}}} &&
|
||||
{{#vars}}
|
||||
{{#isMap}}_deepEquality.equals(other.{{{name}}}, {{{name}}}){{/isMap}}{{^isMap}}{{#isArray}}_deepEquality.equals(other.{{{name}}}, {{{name}}}){{/isArray}}{{^isArray}}other.{{{name}}} == {{{name}}}{{/isArray}}{{/isMap}}{{^-last}} &&{{/-last}}{{#-last}};{{/-last}}
|
||||
{{/vars}}
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
{{#vars}}
|
||||
({{#isNullable}}{{{name}}} == null ? 0 : {{/isNullable}}{{^isNullable}}{{^required}}{{^defaultValue}}{{{name}}} == null ? 0 : {{/defaultValue}}{{/required}}{{/isNullable}}{{{name}}}{{#isNullable}}!{{/isNullable}}{{^isNullable}}{{^required}}{{^defaultValue}}!{{/defaultValue}}{{/required}}{{/isNullable}}.hashCode){{^-last}} +{{/-last}}{{#-last}};{{/-last}}
|
||||
{{/vars}}
|
||||
|
||||
@override
|
||||
String toString() => '{{{classname}}}[{{#vars}}{{{name}}}=${{{name}}}{{^-last}}, {{/-last}}{{/vars}}]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
{{#vars}}
|
||||
{{#vendorExtensions.x-is-optional}}
|
||||
if (this.{{{name}}}.isPresent) {
|
||||
final value = this.{{{name}}}.value;
|
||||
{{#isDateTime}}
|
||||
{{#pattern}}
|
||||
json[r'{{{baseName}}}'] = value == null ? null : (_isEpochMarker(r'{{{pattern}}}')
|
||||
? value.millisecondsSinceEpoch
|
||||
: value.toUtc().toIso8601String());
|
||||
{{/pattern}}
|
||||
{{^pattern}}
|
||||
json[r'{{{baseName}}}'] = value == null ? null : value.toUtc().toIso8601String();
|
||||
{{/pattern}}
|
||||
{{/isDateTime}}
|
||||
{{#isDate}}
|
||||
{{#pattern}}
|
||||
json[r'{{{baseName}}}'] = value == null ? null : (_isEpochMarker(r'{{{pattern}}}')
|
||||
? value.millisecondsSinceEpoch
|
||||
: _dateFormatter.format(value.toUtc()));
|
||||
{{/pattern}}
|
||||
{{^pattern}}
|
||||
json[r'{{{baseName}}}'] = value == null ? null : _dateFormatter.format(value.toUtc());
|
||||
{{/pattern}}
|
||||
{{/isDate}}
|
||||
{{^isDateTime}}
|
||||
{{^isDate}}
|
||||
json[r'{{{baseName}}}'] = value{{#isArray}}{{#uniqueItems}} == null ? null : value.toList(growable: false){{/uniqueItems}}{{/isArray}};
|
||||
{{/isDate}}
|
||||
{{/isDateTime}}
|
||||
}
|
||||
{{/vendorExtensions.x-is-optional}}
|
||||
{{^vendorExtensions.x-is-optional}}
|
||||
{{#isNullable}}
|
||||
if (this.{{{name}}} != null) {
|
||||
{{/isNullable}}
|
||||
{{^isNullable}}
|
||||
{{^required}}
|
||||
{{^defaultValue}}
|
||||
if (this.{{{name}}} != null) {
|
||||
{{/defaultValue}}
|
||||
{{/required}}
|
||||
{{/isNullable}}
|
||||
{{#isDateTime}}
|
||||
{{#pattern}}
|
||||
json[r'{{{baseName}}}'] = _isEpochMarker(r'{{{pattern}}}')
|
||||
? this.{{{name}}}{{#isNullable}}!{{/isNullable}}{{^isNullable}}{{^required}}{{^defaultValue}}!{{/defaultValue}}{{/required}}{{/isNullable}}.millisecondsSinceEpoch
|
||||
: this.{{{name}}}{{#isNullable}}!{{/isNullable}}{{^isNullable}}{{^required}}{{^defaultValue}}!{{/defaultValue}}{{/required}}{{/isNullable}}.toUtc().toIso8601String();
|
||||
{{/pattern}}
|
||||
{{^pattern}}
|
||||
json[r'{{{baseName}}}'] = this.{{{name}}}{{#isNullable}}!{{/isNullable}}{{^isNullable}}{{^required}}{{^defaultValue}}!{{/defaultValue}}{{/required}}{{/isNullable}}.toUtc().toIso8601String();
|
||||
{{/pattern}}
|
||||
{{/isDateTime}}
|
||||
{{#isDate}}
|
||||
{{#pattern}}
|
||||
json[r'{{{baseName}}}'] = _isEpochMarker(r'{{{pattern}}}')
|
||||
? this.{{{name}}}{{#isNullable}}!{{/isNullable}}{{^isNullable}}{{^required}}{{^defaultValue}}!{{/defaultValue}}{{/required}}{{/isNullable}}.millisecondsSinceEpoch
|
||||
: _dateFormatter.format(this.{{{name}}}{{#isNullable}}!{{/isNullable}}{{^isNullable}}{{^required}}{{^defaultValue}}!{{/defaultValue}}{{/required}}{{/isNullable}}.toUtc());
|
||||
{{/pattern}}
|
||||
{{^pattern}}
|
||||
json[r'{{{baseName}}}'] = _dateFormatter.format(this.{{{name}}}{{#isNullable}}!{{/isNullable}}{{^isNullable}}{{^required}}{{^defaultValue}}!{{/defaultValue}}{{/required}}{{/isNullable}}.toUtc());
|
||||
{{/pattern}}
|
||||
{{/isDate}}
|
||||
{{^isDateTime}}
|
||||
{{^isDate}}
|
||||
json[r'{{{baseName}}}'] = this.{{{name}}}{{#isArray}}{{#uniqueItems}}{{#isNullable}}!{{/isNullable}}.toList(growable: false){{/uniqueItems}}{{/isArray}};
|
||||
{{/isDate}}
|
||||
{{/isDateTime}}
|
||||
{{#isNullable}}
|
||||
} else {
|
||||
json[r'{{{baseName}}}'] = null;
|
||||
}
|
||||
{{/isNullable}}
|
||||
{{^isNullable}}
|
||||
{{^required}}
|
||||
{{^defaultValue}}
|
||||
} else {
|
||||
json[r'{{{baseName}}}'] = null;
|
||||
}
|
||||
{{/defaultValue}}
|
||||
{{/required}}
|
||||
{{/isNullable}}
|
||||
{{/vendorExtensions.x-is-optional}}
|
||||
{{/vars}}
|
||||
return json;
|
||||
}
|
||||
|
||||
{{#useFinalProperties}}
|
||||
/// Clones this instance of [{{{classname}}}] and returns a new one where some of the
|
||||
/// properties have changed.
|
||||
{{{classname}}} copyWith({
|
||||
{{#vars}}
|
||||
{{{datatypeWithEnum}}}? {{{name}}},{{#isNullable}}
|
||||
bool {{{name}}}SetToNull = false,{{/isNullable}}
|
||||
{{/vars}}
|
||||
}) => {{{classname}}}(
|
||||
{{#vars}}
|
||||
{{{name}}}: {{#isNullable}}{{{name}}}SetToNull ? null : {{/isNullable}}{{{name}}} ?? this.{{{name}}},
|
||||
{{/vars}}
|
||||
);
|
||||
|
||||
{{/useFinalProperties}}
|
||||
/// Returns a new [{{{classname}}}] instance and imports its values from
|
||||
/// [value] if it's a [Map], null otherwise.
|
||||
// ignore: prefer_constructors_over_static_methods
|
||||
static {{{classname}}}? fromJson(dynamic value) {
|
||||
upgradeDto(value, "{{{classname}}}");
|
||||
if (value is Map) {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return {{{classname}}}(
|
||||
{{#vars}}
|
||||
{{#isDateTime}}
|
||||
{{#vendorExtensions.x-is-optional}}
|
||||
{{{name}}}: json.containsKey(r'{{{baseName}}}') ? Optional.present(mapDateTime(json, r'{{{baseName}}}', r'{{{pattern}}}')) : const Optional.absent(),
|
||||
{{/vendorExtensions.x-is-optional}}
|
||||
{{^vendorExtensions.x-is-optional}}
|
||||
{{{name}}}: mapDateTime(json, r'{{{baseName}}}', r'{{{pattern}}}'){{#required}}{{^isNullable}}!{{/isNullable}}{{/required}}{{^required}}{{#defaultValue}} ?? {{{.}}}{{/defaultValue}}{{/required}},
|
||||
{{/vendorExtensions.x-is-optional}}
|
||||
{{/isDateTime}}
|
||||
{{#isDate}}
|
||||
{{#vendorExtensions.x-is-optional}}
|
||||
{{{name}}}: json.containsKey(r'{{{baseName}}}') ? Optional.present(mapDateTime(json, r'{{{baseName}}}', r'{{{pattern}}}')) : const Optional.absent(),
|
||||
{{/vendorExtensions.x-is-optional}}
|
||||
{{^vendorExtensions.x-is-optional}}
|
||||
{{{name}}}: mapDateTime(json, r'{{{baseName}}}', r'{{{pattern}}}'){{#required}}{{^isNullable}}!{{/isNullable}}{{/required}}{{^required}}{{#defaultValue}} ?? {{{.}}}{{/defaultValue}}{{/required}},
|
||||
{{/vendorExtensions.x-is-optional}}
|
||||
{{/isDate}}
|
||||
{{^isDateTime}}
|
||||
{{^isDate}}
|
||||
{{#complexType}}
|
||||
{{#isArray}}
|
||||
{{#items.isArray}}
|
||||
{{#vendorExtensions.x-is-optional}}
|
||||
{{{name}}}: json.containsKey(r'{{{baseName}}}') ? Optional.present(json[r'{{{baseName}}}'] is List
|
||||
? (json[r'{{{baseName}}}'] as List).map((e) =>
|
||||
{{#items.complexType}}
|
||||
e == null ? {{#items.isNullable}}null{{/items.isNullable}}{{^items.isNullable}}const <{{items.complexType}}>[]{{/items.isNullable}} : {{items.complexType}}.listFromJson(e){{#uniqueItems}}.toSet(){{/uniqueItems}}
|
||||
{{/items.complexType}}
|
||||
{{^items.complexType}}
|
||||
e == null ? {{#items.isNullable}}null{{/items.isNullable}}{{^items.isNullable}}const <{{items.items.dataType}}{{#items.items.isNullable}}?{{/items.items.isNullable}}>[]{{/items.isNullable}} : (e as List).map((value) => value as {{items.items.dataType}}{{#items.items.isNullable}}?{{/items.items.isNullable}}).toList(growable: false)
|
||||
{{/items.complexType}}
|
||||
).toList()
|
||||
: {{#isNullable}}null{{/isNullable}}{{^isNullable}}const []{{/isNullable}}) : const Optional.absent(),
|
||||
{{/vendorExtensions.x-is-optional}}
|
||||
{{^vendorExtensions.x-is-optional}}
|
||||
{{{name}}}: json[r'{{{baseName}}}'] is List
|
||||
? (json[r'{{{baseName}}}'] as List).map((e) =>
|
||||
{{#items.complexType}}
|
||||
e == null ? {{#items.isNullable}}null{{/items.isNullable}}{{^items.isNullable}}const <{{items.complexType}}>[]{{/items.isNullable}} : {{items.complexType}}.listFromJson(e){{#uniqueItems}}.toSet(){{/uniqueItems}}
|
||||
{{/items.complexType}}
|
||||
{{^items.complexType}}
|
||||
e == null ? {{#items.isNullable}}null{{/items.isNullable}}{{^items.isNullable}}const <{{items.items.dataType}}{{#items.items.isNullable}}?{{/items.items.isNullable}}>[]{{/items.isNullable}} : (e as List).map((value) => value as {{items.items.dataType}}{{#items.items.isNullable}}?{{/items.items.isNullable}}).toList(growable: false)
|
||||
{{/items.complexType}}
|
||||
).toList()
|
||||
: {{#isNullable}}null{{/isNullable}}{{^isNullable}}const []{{/isNullable}},
|
||||
{{/vendorExtensions.x-is-optional}}
|
||||
{{/items.isArray}}
|
||||
{{^items.isArray}}
|
||||
{{#vendorExtensions.x-is-optional}}
|
||||
{{{name}}}: json.containsKey(r'{{{baseName}}}') ? Optional.present({{{complexType}}}.listFromJson(json[r'{{{baseName}}}']){{#uniqueItems}}.toSet(){{/uniqueItems}}) : const Optional.absent(),
|
||||
{{/vendorExtensions.x-is-optional}}
|
||||
{{^vendorExtensions.x-is-optional}}
|
||||
{{{name}}}: {{{complexType}}}.listFromJson(json[r'{{{baseName}}}']){{#uniqueItems}}.toSet(){{/uniqueItems}},
|
||||
{{/vendorExtensions.x-is-optional}}
|
||||
{{/items.isArray}}
|
||||
{{/isArray}}
|
||||
{{^isArray}}
|
||||
{{#isMap}}
|
||||
{{#items.isArray}}
|
||||
{{#vendorExtensions.x-is-optional}}
|
||||
{{{name}}}: json.containsKey(r'{{{baseName}}}') ? Optional.present(json[r'{{{baseName}}}'] == null ? null
|
||||
{{#items.complexType}}
|
||||
: {{items.complexType}}.mapListFromJson(json[r'{{{baseName}}}'])) : const Optional.absent(),
|
||||
{{/items.complexType}}
|
||||
{{^items.complexType}}
|
||||
: (json[r'{{{baseName}}}'] as Map<String, dynamic>).map((k, v) => MapEntry(k, v == null ? {{#items.isNullable}}null{{/items.isNullable}}{{^items.isNullable}}const <{{items.items.dataType}}{{#items.items.isNullable}}?{{/items.items.isNullable}}>[]{{/items.isNullable}} : (v as List).map((value) => value as {{items.items.dataType}}{{#items.items.isNullable}}?{{/items.items.isNullable}}).toList(growable: false)))) : const Optional.absent(),
|
||||
{{/items.complexType}}
|
||||
{{/vendorExtensions.x-is-optional}}
|
||||
{{^vendorExtensions.x-is-optional}}
|
||||
{{{name}}}: json[r'{{{baseName}}}'] == null
|
||||
? {{#defaultValue}}{{{.}}}{{/defaultValue}}{{^defaultValue}}null{{/defaultValue}}
|
||||
{{#items.complexType}}
|
||||
: {{items.complexType}}.mapListFromJson(json[r'{{{baseName}}}']),
|
||||
{{/items.complexType}}
|
||||
{{^items.complexType}}
|
||||
: (json[r'{{{baseName}}}'] as Map<String, dynamic>).map((k, v) => MapEntry(k, v == null ? {{#items.isNullable}}null{{/items.isNullable}}{{^items.isNullable}}const <{{items.items.dataType}}{{#items.items.isNullable}}?{{/items.items.isNullable}}>[]{{/items.isNullable}} : (v as List).map((value) => value as {{items.items.dataType}}{{#items.items.isNullable}}?{{/items.items.isNullable}}).toList(growable: false))),
|
||||
{{/items.complexType}}
|
||||
{{/vendorExtensions.x-is-optional}}
|
||||
{{/items.isArray}}
|
||||
{{^items.isArray}}
|
||||
{{#items.isMap}}
|
||||
{{#items.complexType}}
|
||||
{{#vendorExtensions.x-is-optional}}
|
||||
{{{name}}}: json.containsKey(r'{{{baseName}}}') ? Optional.present({{items.complexType}}.mapFromJson(json[r'{{{baseName}}}'])) : const Optional.absent(),
|
||||
{{/vendorExtensions.x-is-optional}}
|
||||
{{^vendorExtensions.x-is-optional}}
|
||||
{{{name}}}: {{items.complexType}}.mapFromJson(json[r'{{{baseName}}}']),
|
||||
{{/vendorExtensions.x-is-optional}}
|
||||
{{/items.complexType}}
|
||||
{{^items.complexType}}
|
||||
{{#vendorExtensions.x-is-optional}}
|
||||
{{{name}}}: json.containsKey(r'{{{baseName}}}') ? Optional.present(mapCastOfType<String, dynamic>(json, r'{{{baseName}}}')) : const Optional.absent(),
|
||||
{{/vendorExtensions.x-is-optional}}
|
||||
{{^vendorExtensions.x-is-optional}}
|
||||
{{{name}}}: mapCastOfType<String, dynamic>(json, r'{{{baseName}}}'){{#required}}{{^isNullable}}!{{/isNullable}}{{/required}}{{^required}}{{#defaultValue}} ?? {{{.}}}{{/defaultValue}}{{/required}},
|
||||
{{/vendorExtensions.x-is-optional}}
|
||||
{{/items.complexType}}
|
||||
{{/items.isMap}}
|
||||
{{^items.isMap}}
|
||||
{{#items.complexType}}
|
||||
{{#vendorExtensions.x-is-optional}}
|
||||
{{{name}}}: json.containsKey(r'{{{baseName}}}') ? Optional.present({{{items.complexType}}}.mapFromJson(json[r'{{{baseName}}}'])) : const Optional.absent(),
|
||||
{{/vendorExtensions.x-is-optional}}
|
||||
{{^vendorExtensions.x-is-optional}}
|
||||
{{{name}}}: {{{items.complexType}}}.mapFromJson(json[r'{{{baseName}}}']),
|
||||
{{/vendorExtensions.x-is-optional}}
|
||||
{{/items.complexType}}
|
||||
{{^items.complexType}}
|
||||
{{#vendorExtensions.x-is-optional}}
|
||||
{{{name}}}: json.containsKey(r'{{{baseName}}}') ? Optional.present(mapCastOfType<String, {{items.dataType}}>(json, r'{{{baseName}}}')) : const Optional.absent(),
|
||||
{{/vendorExtensions.x-is-optional}}
|
||||
{{^vendorExtensions.x-is-optional}}
|
||||
{{{name}}}: mapCastOfType<String, {{items.dataType}}>(json, r'{{{baseName}}}'){{#required}}{{^isNullable}}!{{/isNullable}}{{/required}}{{^required}}{{#defaultValue}} ?? {{{.}}}{{/defaultValue}}{{/required}},
|
||||
{{/vendorExtensions.x-is-optional}}
|
||||
{{/items.complexType}}
|
||||
{{/items.isMap}}
|
||||
{{/items.isArray}}
|
||||
{{/isMap}}
|
||||
{{^isMap}}
|
||||
{{#isBinary}}
|
||||
{{{name}}}: null, // No support for decoding binary content from JSON
|
||||
{{/isBinary}}
|
||||
{{^isBinary}}
|
||||
{{#vendorExtensions.x-is-optional}}
|
||||
{{{name}}}: json.containsKey(r'{{{baseName}}}') ? Optional.present({{{complexType}}}.fromJson(json[r'{{{baseName}}}'])) : const Optional.absent(),
|
||||
{{/vendorExtensions.x-is-optional}}
|
||||
{{^vendorExtensions.x-is-optional}}
|
||||
{{{name}}}: {{{complexType}}}.fromJson(json[r'{{{baseName}}}']){{#required}}{{^isNullable}}!{{/isNullable}}{{/required}}{{^required}}{{#defaultValue}} ?? {{{.}}}{{/defaultValue}}{{/required}},
|
||||
{{/vendorExtensions.x-is-optional}}
|
||||
{{/isBinary}}
|
||||
{{/isMap}}
|
||||
{{/isArray}}
|
||||
{{/complexType}}
|
||||
{{^complexType}}
|
||||
{{#isArray}}
|
||||
{{#isEnum}}
|
||||
{{#vendorExtensions.x-is-optional}}
|
||||
{{{name}}}: json.containsKey(r'{{{baseName}}}') ? Optional.present({{{items.datatypeWithEnum}}}.listFromJson(json[r'{{{baseName}}}']){{#uniqueItems}}.toSet(){{/uniqueItems}}) : const Optional.absent(),
|
||||
{{/vendorExtensions.x-is-optional}}
|
||||
{{^vendorExtensions.x-is-optional}}
|
||||
{{{name}}}: {{{items.datatypeWithEnum}}}.listFromJson(json[r'{{{baseName}}}']){{#uniqueItems}}.toSet(){{/uniqueItems}},
|
||||
{{/vendorExtensions.x-is-optional}}
|
||||
{{/isEnum}}
|
||||
{{^isEnum}}
|
||||
{{#vendorExtensions.x-is-optional}}
|
||||
{{{name}}}: json.containsKey(r'{{{baseName}}}') ? Optional.present(json[r'{{{baseName}}}'] is Iterable
|
||||
? (json[r'{{{baseName}}}'] as Iterable).cast<{{{items.datatype}}}>().{{#uniqueItems}}toSet(){{/uniqueItems}}{{^uniqueItems}}toList(growable: false){{/uniqueItems}}
|
||||
: {{#defaultValue}}{{{.}}}{{/defaultValue}}{{^defaultValue}}null{{/defaultValue}}) : const Optional.absent(),
|
||||
{{/vendorExtensions.x-is-optional}}
|
||||
{{^vendorExtensions.x-is-optional}}
|
||||
{{{name}}}: json[r'{{{baseName}}}'] is Iterable
|
||||
? (json[r'{{{baseName}}}'] as Iterable).cast<{{{items.datatype}}}>().{{#uniqueItems}}toSet(){{/uniqueItems}}{{^uniqueItems}}toList(growable: false){{/uniqueItems}}
|
||||
: {{#defaultValue}}{{{.}}}{{/defaultValue}}{{^defaultValue}}null{{/defaultValue}},
|
||||
{{/vendorExtensions.x-is-optional}}
|
||||
{{/isEnum}}
|
||||
{{/isArray}}
|
||||
{{^isArray}}
|
||||
{{#isMap}}
|
||||
{{#vendorExtensions.x-is-optional}}
|
||||
{{{name}}}: json.containsKey(r'{{{baseName}}}') ? Optional.present(mapCastOfType<String, {{{items.datatype}}}>(json, r'{{{baseName}}}')) : const Optional.absent(),
|
||||
{{/vendorExtensions.x-is-optional}}
|
||||
{{^vendorExtensions.x-is-optional}}
|
||||
{{{name}}}: mapCastOfType<String, {{{items.datatype}}}>(json, r'{{{baseName}}}'){{#required}}{{^isNullable}}!{{/isNullable}}{{/required}}{{^required}}{{#defaultValue}} ?? {{{.}}}{{/defaultValue}}{{/required}},
|
||||
{{/vendorExtensions.x-is-optional}}
|
||||
{{/isMap}}
|
||||
{{^isMap}}
|
||||
{{#isNumber}}
|
||||
{{#vendorExtensions.x-is-optional}}
|
||||
{{{name}}}: json.containsKey(r'{{{baseName}}}') ? Optional.present(json[r'{{{baseName}}}'] == null ? null : num.parse('${json[r'{{{baseName}}}']}')) : const Optional.absent(),
|
||||
{{/vendorExtensions.x-is-optional}}
|
||||
{{^vendorExtensions.x-is-optional}}
|
||||
{{{name}}}: {{#isNullable}}json[r'{{{baseName}}}'] == null
|
||||
? {{#defaultValue}}{{{.}}}{{/defaultValue}}{{^defaultValue}}null{{/defaultValue}}
|
||||
: {{/isNullable}}{{{datatypeWithEnum}}}.parse('${json[r'{{{baseName}}}']}'),
|
||||
{{/vendorExtensions.x-is-optional}}
|
||||
{{/isNumber}}
|
||||
{{^isNumber}}
|
||||
{{#vendorExtensions.x-original-is-integer}}
|
||||
{{{name}}}: json.containsKey(r'{{{baseName}}}') ? Optional.present(json[r'{{{baseName}}}'] == null ? null : int.parse('${json[r'{{{baseName}}}']}')) : const Optional.absent(),
|
||||
{{/vendorExtensions.x-original-is-integer}}
|
||||
{{^vendorExtensions.x-original-is-integer}}
|
||||
{{#vendorExtensions.x-original-is-number}}
|
||||
{{{name}}}: json.containsKey(r'{{{baseName}}}') ? Optional.present(json[r'{{{baseName}}}'] == null ? null : num.parse('${json[r'{{{baseName}}}']}')) : const Optional.absent(),
|
||||
{{/vendorExtensions.x-original-is-number}}
|
||||
{{^vendorExtensions.x-original-is-number}}
|
||||
{{^isEnum}}
|
||||
{{#vendorExtensions.x-is-optional}}
|
||||
{{{name}}}: json.containsKey(r'{{{baseName}}}') ? Optional.present(mapValueOfType<{{#vendorExtensions.x-unwrapped-datatype}}{{{vendorExtensions.x-unwrapped-datatype}}}{{/vendorExtensions.x-unwrapped-datatype}}{{^vendorExtensions.x-unwrapped-datatype}}{{{datatypeWithEnum}}}{{/vendorExtensions.x-unwrapped-datatype}}>(json, r'{{{baseName}}}')) : const Optional.absent(),
|
||||
{{/vendorExtensions.x-is-optional}}
|
||||
{{^vendorExtensions.x-is-optional}}
|
||||
{{{name}}}: mapValueOfType<{{{datatypeWithEnum}}}>(json, r'{{{baseName}}}'){{#required}}{{^isNullable}}!{{/isNullable}}{{/required}}{{^required}}{{#defaultValue}} ?? {{{.}}}{{/defaultValue}}{{/required}},
|
||||
{{/vendorExtensions.x-is-optional}}
|
||||
{{/isEnum}}
|
||||
{{#isEnum}}
|
||||
{{#vendorExtensions.x-is-optional}}
|
||||
{{{name}}}: json.containsKey(r'{{{baseName}}}') ? Optional.present({{{enumName}}}.fromJson(json[r'{{{baseName}}}'])) : const Optional.absent(),
|
||||
{{/vendorExtensions.x-is-optional}}
|
||||
{{^vendorExtensions.x-is-optional}}
|
||||
{{{name}}}: {{{enumName}}}.fromJson(json[r'{{{baseName}}}']){{#required}}{{^isNullable}}!{{/isNullable}}{{/required}}{{^required}}{{#defaultValue}} ?? const {{{enumName}}}._({{{.}}}){{/defaultValue}}{{/required}},
|
||||
{{/vendorExtensions.x-is-optional}}
|
||||
{{/isEnum}}
|
||||
{{/vendorExtensions.x-original-is-number}}
|
||||
{{/vendorExtensions.x-original-is-integer}}
|
||||
{{/isNumber}}
|
||||
{{/isMap}}
|
||||
{{/isArray}}
|
||||
{{/complexType}}
|
||||
{{/isDate}}
|
||||
{{/isDateTime}}
|
||||
{{/vars}}
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static List<{{{classname}}}> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <{{{classname}}}>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = {{{classname}}}.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
|
||||
static Map<String, {{{classname}}}> mapFromJson(dynamic json) {
|
||||
final map = <String, {{{classname}}}>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = {{{classname}}}.fromJson(entry.value);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// maps a json object with a list of {{{classname}}}-objects as value to a dart map
|
||||
static Map<String, List<{{{classname}}}>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||
final map = <String, List<{{{classname}}}>>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
// ignore: parameter_assignments
|
||||
json = json.cast<String, dynamic>();
|
||||
for (final entry in json.entries) {
|
||||
map[entry.key] = {{{classname}}}.listFromJson(entry.value, growable: growable,);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
{{#vars}}
|
||||
{{#required}}
|
||||
'{{{baseName}}}',
|
||||
{{/required}}
|
||||
{{/vars}}
|
||||
};
|
||||
}
|
||||
{{#vars}}
|
||||
{{^isModel}}
|
||||
{{#isEnum}}
|
||||
{{^isContainer}}
|
||||
|
||||
{{>serialization/native/native_enum_inline}}
|
||||
|
||||
{{/isContainer}}
|
||||
{{#isContainer}}
|
||||
{{#mostInnerItems}}
|
||||
|
||||
{{>serialization/native/native_enum_inline}}
|
||||
|
||||
{{/mostInnerItems}}
|
||||
{{/isContainer}}
|
||||
{{/isEnum}}
|
||||
{{/isModel}}
|
||||
{{/vars}}
|
||||
Loading…
Add table
Add a link
Reference in a new issue