Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
330526f
PoC json_serializable in dart-dio-next
MichaelMarner Jul 20, 2021
eef247d
Move build.yaml template into json_serializable dir
MichaelMarner Jul 26, 2021
acddd80
Undo implicit-dynamic change
MichaelMarner Jul 26, 2021
cabdbda
Fix automatic formatting
MichaelMarner Jul 27, 2021
2c5ef70
Treat non-required fields as nullable
MichaelMarner Oct 26, 2021
693227c
Make class properties final
MichaelMarner Oct 26, 2021
e1c9571
Fix error introduced by merging in master
MichaelMarner Oct 26, 2021
b35785c
Fix map creation when deserializing
MichaelMarner Oct 27, 2021
36f47e7
Exclude built files from analysis
MichaelMarner Oct 27, 2021
0feda9b
Add new dio import props
MichaelMarner Oct 27, 2021
dc34a8a
Fix broken merge
MichaelMarner Oct 27, 2021
237bdc4
Fix configuration of nullable properties
MichaelMarner Oct 29, 2021
5d4fa0f
Only add api_util import if using built value
MichaelMarner Nov 4, 2021
f336c78
Add config param to set properties as final
MichaelMarner Dec 2, 2021
a3ab5d2
Fix syntax error due to merge
MichaelMarner Apr 12, 2022
4f3f64f
Update to simplified dio configuration
MichaelMarner Apr 12, 2022
3a2cb03
Merge branch 'master' into dart-dio-next-json-serializable
MichaelMarner Apr 12, 2022
019084a
Add missing api constructor template
MichaelMarner Apr 12, 2022
d6af303
Merge branch 'dart-dio-next-json-serializable' of github.com:MichaelM…
MichaelMarner Apr 12, 2022
f9c7e21
Fix import for multipart files
MichaelMarner Apr 12, 2022
826b465
Fix inclusion of library deserialize template
MichaelMarner Apr 12, 2022
6d185a1
Update docs
MichaelMarner Apr 12, 2022
a78f410
Remove trailing newline from class
MichaelMarner Apr 12, 2022
8e8cb4f
Fix whitespace in generated templates
MichaelMarner Apr 12, 2022
a820c44
FIx built value generation problem caused by merge conflicts
MichaelMarner Apr 12, 2022
6e2a3ae
Escape dollar signs in strings
MichaelMarner Apr 13, 2022
de62845
Handle enums
MichaelMarner Apr 13, 2022
3c56734
Config for json_serializable sample
MichaelMarner Apr 13, 2022
4203144
Generate sample for json_serializable
MichaelMarner Apr 13, 2022
87608f7
Revert "Escape dollar signs in strings"
MichaelMarner Apr 13, 2022
4c41ddb
Use raw strings when dealing with enum values
MichaelMarner Apr 13, 2022
78f075a
Add json_serializable Maven module ind fix number based enums
kuhnroyal Apr 13, 2022
25eb6bc
Merge pull request #3 from kuhnroyal/dart-dio-next-json-serializable
MichaelMarner Apr 14, 2022
5006f9e
Update docs and fix wrong maven module
kuhnroyal Apr 14, 2022
76f2d2c
Merge remote-tracking branch 'OpenAPITools/master' into dart-dio-next…
kuhnroyal Apr 14, 2022
4080525
Merge pull request #4 from kuhnroyal/dart-dio-next-json-serializable
MichaelMarner Apr 21, 2022
67ec4ed
Merge remote-tracking branch 'upstream/master' into dart-dio-next-jso…
MichaelMarner Apr 27, 2022
a016b88
Update minimum dart sdk with json serializable
MichaelMarner Apr 27, 2022
b894e14
Use dart 2.14 when testing Dart samples
MichaelMarner Apr 27, 2022
cf5ceef
Update codegen to remove analysis errors in output
MichaelMarner Apr 27, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/samples-dart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:
key: ${{ runner.os }}-${{ github.job }}-${{ env.cache-name }}-${{ hashFiles('samples/**/pubspec.yaml') }}
- uses: dart-lang/setup-dart@v1
with:
sdk: 2.13.0
sdk: 2.14.0
- name: Run tests
uses: ./.github/actions/run-samples
with:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
generatorName: dart-dio-next
outputDir: samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake-json_serializable
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml
templateDir: modules/openapi-generator/src/main/resources/dart/libraries/dio
typeMappings:
Client: "ModelClient"
File: "ModelFile"
EnumClass: "ModelEnumClass"
additionalProperties:
hideGenerationTimestamp: "true"
enumUnknownDefaultCase: "true"
serializationLibrary: "json_serializable"
3 changes: 2 additions & 1 deletion docs/generators/dart-dio-next.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|disallowAdditionalPropertiesIfNotPresent|If false, the 'additionalProperties' implementation (set to true by default) is compliant with the OAS and JSON schema specifications. If true (default), keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.|<dl><dt>**false**</dt><dd>The 'additionalProperties' implementation is compliant with the OAS and JSON schema specifications.</dd><dt>**true**</dt><dd>Keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.</dd></dl>|true|
|ensureUniqueParams|Whether to ensure parameter names are unique in an operation (rename parameters that are not).| |true|
|enumUnknownDefaultCase|If the server adds new enum cases, that are unknown by an old spec/client, the client will fail to parse the network response.With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the server sends an enum case that is not known by the client/spec, they can safely fallback to this case.|<dl><dt>**false**</dt><dd>No changes to the enum's are made, this is the default option.</dd><dt>**true**</dt><dd>With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the enum case sent by the server is not known by the client/spec, can safely be decoded to this case.</dd></dl>|false|
|finalProperties|Whether properties are marked as final when using Json Serializable for serialization| |true|
|legacyDiscriminatorBehavior|Set to false for generators with better support for discriminators. (Python, Java, Go, PowerShell, C#have this enabled by default).|<dl><dt>**true**</dt><dd>The mapping in the discriminator includes descendent schemas that allOf inherit from self and the discriminator mapping schemas in the OAS document.</dd><dt>**false**</dt><dd>The mapping in the discriminator includes any descendent schemas that allOf inherit from self, any oneOf schemas, any anyOf schemas, any x-discriminator-values, and the discriminator mapping schemas in the OAS document AND Codegen validates that oneOf and anyOf schemas contain the required discriminator and throws an error if the discriminator is missing.</dd></dl>|true|
|prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false|
|pubAuthor|Author name in generated pubspec| |Author|
Expand All @@ -32,7 +33,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|pubLibrary|Library name in generated code| |openapi.api|
|pubName|Name in generated pubspec| |openapi|
|pubVersion|Version in generated pubspec| |1.0.0|
|serializationLibrary|Specify serialization library|<dl><dt>**built_value**</dt><dd>[DEFAULT] built_value</dd></dl>|built_value|
|serializationLibrary|Specify serialization library|<dl><dt>**built_value**</dt><dd>[DEFAULT] built_value</dd><dt>**json_serializable**</dt><dd>[BETA] json_serializable</dd></dl>|built_value|
|sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true|
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true|
|sourceFolder|source folder for generated code| |src|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,13 @@ public class DartDioNextClientCodegen extends AbstractDartCodegen {
public static final String DATE_LIBRARY_DEFAULT = DATE_LIBRARY_CORE;

public static final String SERIALIZATION_LIBRARY_BUILT_VALUE = "built_value";
public static final String SERIALIZATION_LIBRARY_JSON_SERIALIZABLE = "json_serializable";
public static final String SERIALIZATION_LIBRARY_DEFAULT = SERIALIZATION_LIBRARY_BUILT_VALUE;

private static final String DIO_IMPORT = "package:dio/dio.dart";
public static final String FINAL_PROPERTIES = "finalProperties";
public static final String FINAL_PROPERTIES_DEFAULT_VALUE = "true";

private static final String CLIENT_NAME = "clientName";

private String dateLibrary;
Expand All @@ -85,11 +89,17 @@ public DartDioNextClientCodegen() {
this.setTemplateDir(embeddedTemplateDir);

supportedLibraries.put(SERIALIZATION_LIBRARY_BUILT_VALUE, "[DEFAULT] built_value");
supportedLibraries.put(SERIALIZATION_LIBRARY_JSON_SERIALIZABLE, "[BETA] json_serializable");
final CliOption serializationLibrary = CliOption.newString(CodegenConstants.SERIALIZATION_LIBRARY, "Specify serialization library");
serializationLibrary.setEnum(supportedLibraries);
serializationLibrary.setDefault(SERIALIZATION_LIBRARY_DEFAULT);
cliOptions.add(serializationLibrary);

final CliOption finalProperties = CliOption.newBoolean(FINAL_PROPERTIES, "Whether properties are marked as final when using Json Serializable for serialization");
finalProperties.setDefault("true");
cliOptions.add(finalProperties);

// Date Library Option
final CliOption dateOption = CliOption.newString(DATE_LIBRARY, "Specify Date library");
dateOption.setDefault(DATE_LIBRARY_DEFAULT);

Expand Down Expand Up @@ -147,6 +157,14 @@ public void processOpts() {
}
setDateLibrary(additionalProperties.get(DATE_LIBRARY).toString());

if (!additionalProperties.containsKey(FINAL_PROPERTIES)) {
additionalProperties.put(FINAL_PROPERTIES, Boolean.parseBoolean(FINAL_PROPERTIES_DEFAULT_VALUE));
LOGGER.debug("finalProperties not set, using default {}", FINAL_PROPERTIES_DEFAULT_VALUE);
}
else {
additionalProperties.put(FINAL_PROPERTIES, Boolean.parseBoolean(additionalProperties.get(FINAL_PROPERTIES).toString()));
}

if (!additionalProperties.containsKey(CLIENT_NAME)) {
final String name = org.openapitools.codegen.utils.StringUtils.camelize(pubName);
additionalProperties.put(CLIENT_NAME, name);
Expand Down Expand Up @@ -177,6 +195,10 @@ public void processOpts() {

private void configureSerializationLibrary(String srcFolder) {
switch (library) {
case SERIALIZATION_LIBRARY_JSON_SERIALIZABLE:
additionalProperties.put("useJsonSerializable", "true");
configureSerializationLibraryJsonSerializable(srcFolder);
break;
default:
case SERIALIZATION_LIBRARY_BUILT_VALUE:
additionalProperties.put("useBuiltValue", "true");
Expand Down Expand Up @@ -229,6 +251,18 @@ private void configureSerializationLibraryBuiltValue(String srcFolder) {
imports.put("MultipartFile", DIO_IMPORT);
}

private void configureSerializationLibraryJsonSerializable(String srcFolder) {
supportingFiles.add(new SupportingFile("serialization/json_serializable/build.yaml.mustache", "" /* main project dir */, "build.yaml"));
supportingFiles.add(new SupportingFile("serialization/json_serializable/deserialize.mustache", srcFolder,
"deserialize.dart"));

// most of these are defined in AbstractDartCodegen, we are overriding
// just the binary / file handling
languageSpecificPrimitives.add("Object");
imports.put("Uint8List", "dart:typed_data");
imports.put("MultipartFile", DIO_IMPORT);
}

private void configureDateLibrary(String srcFolder) {
switch (dateLibrary) {
case DATE_LIBRARY_TIME_MACHINE:
Expand Down Expand Up @@ -362,27 +396,30 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<Mo
op.imports.remove("Uint8List");
}

for (CodegenParameter param : op.allParams) {
// Generate serializer factories for all container type parameters.
// But skip binary and file parameters, JSON serializers don't make sense there.
if (param.isContainer && !(param.isBinary || param.isFile )) {
addBuiltValueSerializer(new BuiltValueSerializer(
param.isArray,
param.uniqueItems,
param.isMap,
param.items.isNullable,
param.baseType
));
resultImports.addAll(rewriteImports(op.imports, false));

if (SERIALIZATION_LIBRARY_BUILT_VALUE.equals(library)) {

for (CodegenParameter param : op.allParams) {
// Generate serializer factories for all container type parameters.
// But skip binary and file parameters, JSON serializers don't make sense there.
if (param.isContainer && !(param.isBinary || param.isFile )) {
addBuiltValueSerializer(new BuiltValueSerializer(
param.isArray,
param.uniqueItems,
param.isMap,
param.items.isNullable,
param.baseType
));
}
}
}

resultImports.addAll(rewriteImports(op.imports, false));
if (op.getHasFormParams() || op.getHasQueryParams()) {
if (SERIALIZATION_LIBRARY_BUILT_VALUE.equals(library) && (op.getHasFormParams() || op.getHasQueryParams())) {
resultImports.add("package:" + pubName + "/" + sourceFolder + "/api_util.dart");
}

// Generate serializer factories for response types.
// But skip binary and file response, JSON serializers don't make sense there.
if (op.returnContainer != null && !(op.isResponseBinary || op.isResponseFile)) {
addBuiltValueSerializer(new BuiltValueSerializer(
Objects.equals("array", op.returnContainer) || Objects.equals("set", op.returnContainer),
Expand All @@ -393,7 +430,6 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<Mo
));
}
}

// for some reason "import" structure is changed ..
objs.put("imports", resultImports.stream().sorted().collect(Collectors.toList()));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ analyzer:
implicit-dynamic: false
implicit-casts: false
exclude:
- test/*.dart
- test/*.dart{{#useJsonSerializable}}
- lib/src/model/*.g.dart{{/useJsonSerializable}}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ import 'package:{{pubName}}/{{pubName}}.dart';
void main() {
{{^isEnum}}
{{! Due to required vars without default value we can not create a full instance here }}
final instance = {{{classname}}}Builder();
// TODO add properties to the builder and call build()
{{#includeLibraryTemplate}}test_instance{{/includeLibraryTemplate}}
{{/isEnum}}

group({{{classname}}}, () {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,22 @@ description: {{pubDescription}}
homepage: {{pubHomepage}}

environment:
{{#useBuiltValue}}
sdk: '>=2.12.0 <3.0.0'
{{/useBuiltValue}}
{{#useJsonSerializable}}
sdk: '>=2.14.0 <3.0.0'
{{/useJsonSerializable}}

dependencies:
dio: '>=4.0.0 <5.0.0'
{{#useBuiltValue}}
built_value: '>=8.1.0 <9.0.0'
built_collection: '>=5.1.0 <6.0.0'
{{/useBuiltValue}}
{{#useJsonSerializable}}
json_annotation: '^4.4.0'
{{/useJsonSerializable}}
{{#useDateLibTimeMachine}}
time_machine: ^0.9.16
{{/useDateLibTimeMachine}}
Expand All @@ -21,4 +29,8 @@ dev_dependencies:
built_value_generator: '>=8.1.0 <9.0.0'
build_runner: any
{{/useBuiltValue}}
{{#useJsonSerializable}}
build_runner: any
json_serializable: '^6.1.5'
{{/useJsonSerializable}}
test: ^1.16.0
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
final instance = {{{classname}}}Builder();
// TODO add properties to the builder and call build()
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
const {{classname}}(this._dio);
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
_responseData = deserialize<{{{returnType}}}, {{{returnBaseType}}}>(_response.data!, '{{{returnType}}}', growable: true);
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// ignore: unused_import
import 'dart:convert';
import 'package:{{pubName}}/src/deserialize.dart';
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{{{paramName}}}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{{#bodyParam}}_bodyData=jsonEncode({{{paramName}}});{{/bodyParam}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
targets:
$default:
builders:
json_serializable:
options:
# Options configure how source code is generated for every
# `@JsonSerializable`-annotated class in the package.
#
# The default value for each is listed.
any_map: false
checked: true
create_factory: true
create_to_json: true
disallow_unrecognized_keys: true
explicit_to_json: true
field_rename: none
ignore_unannotated: false
include_if_null: false
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import 'package:json_annotation/json_annotation.dart';

part '{{classFilename}}.g.dart';

{{!
Classes with polymorphism or composition may generate unused imports,
these need to be ignored for said classes so that there are no lint errors.
}}
{{#parentModel}}
// ignore_for_file: unused_import

{{/parentModel}}

@JsonSerializable(
checked: true,
createToJson: true,
disallowUnrecognizedKeys: false,
explicitToJson: true,
)
class {{{classname}}} {
{{>serialization/json_serializable/dart_constructor}}

{{#vars}}
{{#description}}
/// {{{description}}}
{{/description}}
{{^isEnum}}
{{#minimum}}
// minimum: {{{minimum}}}
{{/minimum}}
{{#maximum}}
// maximum: {{{maximum}}}
{{/maximum}}
{{/isEnum}}
{{^isBinary}}
@JsonKey(
{{#defaultValue}}defaultValue: {{{defaultValue}}},{{/defaultValue}}
name: r'{{{baseName}}}',
required: {{#required}}true{{/required}}{{^required}}false{{/required}},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs includeIfNull to be used in conjunction with required. If field is required, then null value must be included

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe I have addressed this now

includeIfNull: {{#required}}{{#isNullable}}true{{/isNullable}}false{{/required}}{{^required}}false{{/required}}
)
{{/isBinary}}
{{#isBinary}}
@JsonKey(ignore: true)
{{/isBinary}}


{{#required}}
{{#finalProperties}}final {{/finalProperties}}{{{datatypeWithEnum}}}{{#isNullable}}?{{/isNullable}} {{{name}}};
{{/required}}
{{^required}}
{{#finalProperties}}final {{/finalProperties}}{{{datatypeWithEnum}}}? {{{name}}};
{{/required}}



{{/vars}}
@override
bool operator ==(Object other) => identical(this, other) || other is {{{classname}}} &&
{{#vars}}
other.{{{name}}} == {{{name}}}{{^-last}} &&{{/-last}}{{#-last}};{{/-last}}
{{/vars}}

@override
int get hashCode =>
{{#vars}}
{{#isNullable}}({{{name}}} == null ? 0 : {{{name}}}.hashCode){{/isNullable}}{{^isNullable}}{{{name}}}.hashCode{{/isNullable}}{{^-last}} +{{/-last}}{{#-last}};{{/-last}}
{{/vars}}

factory {{{classname}}}.fromJson(Map<String, dynamic> json) => _${{{classname}}}FromJson(json);

Map<String, dynamic> toJson() => _${{{classname}}}ToJson(this);

@override
String toString() {
return toJson().toString();
}

}
{{#vars}}
{{#isEnum}}
{{^isContainer}}

{{>serialization/json_serializable/enum_inline}}
{{/isContainer}}
{{#isContainer}}
{{#mostInnerItems}}

{{>serialization/json_serializable/enum_inline}}
{{/mostInnerItems}}
{{/isContainer}}
{{/isEnum}}
{{/vars}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/// Returns a new [{{{classname}}}] instance.
{{{classname}}}({
{{#vars}}

{{!
A field is required in Dart when it is
required && !defaultValue in OAS
}}
{{#required}}{{^defaultValue}}required {{/defaultValue}}{{/required}} this.{{{name}}}{{#defaultValue}} = {{#isEnum}}{{^isContainer}}const {{{enumName}}}._({{/isContainer}}{{/isEnum}}{{{defaultValue}}}{{#isEnum}}{{^isContainer}}){{/isContainer}}{{/isEnum}}{{/defaultValue}},
{{/vars}}
});
Loading