[dart][dio][built_value] Fix missing serializer factory builders for additionalProperties (#11011)

Refactor the addition of custom serializer factories.
This commit is contained in:
Peter Leibiger
2021-12-04 07:32:36 +01:00
committed by GitHub
parent 85985e8bfb
commit ecddd4cff1
5 changed files with 121 additions and 47 deletions

View File

@@ -505,7 +505,7 @@ public abstract class AbstractDartCodegen extends DefaultCodegen {
super.postProcessModelProperty(model, property);
if (!model.isEnum && property.isEnum) {
// These are inner enums, enums which do not exist as models, just as properties.
// They are handled via the enum_inline template and and are generated in the
// They are handled via the enum_inline template and are generated in the
// same file as the containing class. To prevent name clashes the inline enum classes
// are prefix with the classname of the containing class in the template.
// Here the datatypeWithEnum template variable gets updated to match that scheme.
@@ -529,9 +529,9 @@ public abstract class AbstractDartCodegen extends DefaultCodegen {
public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, List<Server> servers) {
final CodegenOperation op = super.fromOperation(path, httpMethod, operation, servers);
for (CodegenResponse r : op.responses) {
// By default only set types are automatically added to operation imports, not sure why.
// By default, only set types are automatically added to operation imports, not sure why.
// Add all container type imports here, by default 'dart:core' imports are skipped
// but other sub classes may required specific container type imports.
// but other sub-classes may require specific container type imports.
if (r.containerType != null && typeMapping().containsKey(r.containerType)) {
final String value = typeMapping().get(r.containerType);
if (needToImport(value)) {

View File

@@ -323,6 +323,21 @@ public class DartDioNextClientCodegen extends AbstractDartCodegen {
// enums are generated with built_value and make use of BuiltSet
model.imports.add("BuiltSet");
}
if (property.isContainer) {
// Figure out if there are any container type additionalProperties
// that need a custom serializer builder factory added.
final CodegenProperty items = property.items;
if (items.getAdditionalProperties() != null) {
addBuiltValueSerializer(new BuiltValueSerializer(
items.isArray,
items.getUniqueItems(),
items.isMap,
items.items.isNullable,
items.getAdditionalProperties().dataType
));
}
}
}
}
@@ -332,7 +347,6 @@ public class DartDioNextClientCodegen extends AbstractDartCodegen {
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
List<CodegenOperation> operationList = (List<CodegenOperation>) operations.get("operation");
Set<Map<String, Object>> serializers = new HashSet<>();
Set<String> resultImports = new HashSet<>();
for (CodegenOperation op : operationList) {
@@ -370,12 +384,13 @@ public class DartDioNextClientCodegen extends AbstractDartCodegen {
// 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 )) {
final Map<String, Object> serializer = new HashMap<>();
serializer.put("isArray", param.isArray);
serializer.put("uniqueItems", param.uniqueItems);
serializer.put("isMap", param.isMap);
serializer.put("baseType", param.baseType);
serializers.add(serializer);
addBuiltValueSerializer(new BuiltValueSerializer(
param.isArray,
param.uniqueItems,
param.isMap,
param.items.isNullable,
param.baseType
));
}
}
@@ -387,17 +402,17 @@ public class DartDioNextClientCodegen extends AbstractDartCodegen {
// 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)) {
final Map<String, Object> serializer = new HashMap<>();
serializer.put("isArray", Objects.equals("array", op.returnContainer) || Objects.equals("set", op.returnContainer));
serializer.put("uniqueItems", op.uniqueItems);
serializer.put("isMap", Objects.equals("map", op.returnContainer));
serializer.put("baseType", op.returnBaseType);
serializers.add(serializer);
addBuiltValueSerializer(new BuiltValueSerializer(
Objects.equals("array", op.returnContainer) || Objects.equals("set", op.returnContainer),
op.uniqueItems,
Objects.equals("map", op.returnContainer),
false,
op.returnBaseType
));
}
}
objs.put("imports", resultImports.stream().sorted().collect(Collectors.toList()));
objs.put("serializers", serializers);
return objs;
}
@@ -410,6 +425,19 @@ public class DartDioNextClientCodegen extends AbstractDartCodegen {
});
}
/**
* Adds the serializer to the global list of custom built_value serializers.
* @param serializer
*/
private void addBuiltValueSerializer(BuiltValueSerializer serializer) {
System.out.println("######## Add serializer!");
additionalProperties.compute("builtValueSerializers", (k, v) -> {
Set<BuiltValueSerializer> serializers = v == null ? Sets.newHashSet() : ((Set<BuiltValueSerializer>) v);
serializers.add(serializer);
return serializers;
});
}
private Set<String> rewriteImports(Set<String> originalImports, boolean isModel) {
Set<String> resultImports = Sets.newHashSet();
for (String modelImport : originalImports) {
@@ -428,4 +456,58 @@ public class DartDioNextClientCodegen extends AbstractDartCodegen {
}
return resultImports;
}
static class BuiltValueSerializer {
final boolean isArray;
final boolean uniqueItems;
final boolean isMap;
final boolean isNullable;
final String dataType;
private BuiltValueSerializer(boolean isArray, boolean uniqueItems, boolean isMap, boolean isNullable, String dataType) {
this.isArray = isArray;
this.uniqueItems = uniqueItems;
this.isMap = isMap;
this.isNullable = isNullable;
this.dataType = dataType;
}
public boolean isArray() {
return isArray;
}
public boolean isUniqueItems() {
return uniqueItems;
}
public boolean isMap() {
return isMap;
}
public boolean isNullable() {
return isNullable;
}
public String getDataType() {
return dataType;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BuiltValueSerializer that = (BuiltValueSerializer) o;
return isArray == that.isArray && uniqueItems == that.uniqueItems && isMap == that.isMap && isNullable == that.isNullable && dataType.equals(that.dataType);
}
@Override
public int hashCode() {
return Objects.hash(isArray, uniqueItems, isMap, isNullable, dataType);
}
}
}

View File

@@ -19,17 +19,17 @@ part 'serializers.g.dart';
@SerializersFor([{{#models}}{{#model}}
{{classname}},{{/model}}{{/models}}
])
Serializers serializers = (_$serializers.toBuilder(){{#apiInfo}}{{#apis}}{{#serializers}}
Serializers serializers = (_$serializers.toBuilder(){{#builtValueSerializers}}
..addBuilderFactory(
{{#isArray}}
const FullType(Built{{#uniqueItems}}Set{{/uniqueItems}}{{^uniqueItems}}List{{/uniqueItems}}, [FullType({{baseType}})]),
() => {{#uniqueItems}}Set{{/uniqueItems}}{{^uniqueItems}}List{{/uniqueItems}}Builder<{{baseType}}>(),
const FullType(Built{{#uniqueItems}}Set{{/uniqueItems}}{{^uniqueItems}}List{{/uniqueItems}}, [FullType{{#isNullable}}.nullable{{/isNullable}}({{dataType}})]),
() => {{#uniqueItems}}Set{{/uniqueItems}}{{^uniqueItems}}List{{/uniqueItems}}Builder<{{dataType}}>(),
{{/isArray}}
{{#isMap}}
const FullType(BuiltMap, [FullType(String), FullType({{baseType}})]),
() => MapBuilder<String, {{baseType}}>(),
const FullType(BuiltMap, [FullType(String), FullType{{#isNullable}}.nullable{{/isNullable}}({{dataType}})]),
() => MapBuilder<String, {{dataType}}>(),
{{/isMap}}
){{/serializers}}{{/apis}}{{/apiInfo}}{{#useDateLibTimeMachine}}
){{/builtValueSerializers}}{{#useDateLibTimeMachine}}
..add(const OffsetDateSerializer())
..add(const OffsetDateTimeSerializer()){{/useDateLibTimeMachine}}{{#useDateLibCore}}
..add(const DateSerializer())

View File

@@ -110,26 +110,22 @@ part 'serializers.g.dart';
User,
])
Serializers serializers = (_$serializers.toBuilder()
..addBuilderFactory(
const FullType(BuiltList, [FullType(String)]),
() => ListBuilder<String>(),
)
..addBuilderFactory(
const FullType(BuiltMap, [FullType(String), FullType(String)]),
() => MapBuilder<String, String>(),
)
..addBuilderFactory(
const FullType(BuiltList, [FullType(String)]),
() => ListBuilder<String>(),
)
..addBuilderFactory(
const FullType(BuiltSet, [FullType(Pet)]),
() => SetBuilder<Pet>(),
const FullType(BuiltList, [FullType(User)]),
() => ListBuilder<User>(),
)
..addBuilderFactory(
const FullType(BuiltSet, [FullType(String)]),
() => SetBuilder<String>(),
)
..addBuilderFactory(
const FullType(BuiltSet, [FullType(Pet)]),
() => SetBuilder<Pet>(),
)
..addBuilderFactory(
const FullType(BuiltList, [FullType(Pet)]),
() => ListBuilder<Pet>(),
@@ -139,8 +135,8 @@ Serializers serializers = (_$serializers.toBuilder()
() => MapBuilder<String, int>(),
)
..addBuilderFactory(
const FullType(BuiltList, [FullType(User)]),
() => ListBuilder<User>(),
const FullType(BuiltList, [FullType(String)]),
() => ListBuilder<String>(),
)
..add(const DateSerializer())
..add(Iso8601DateTimeSerializer()))

View File

@@ -110,26 +110,22 @@ part 'serializers.g.dart';
User,
])
Serializers serializers = (_$serializers.toBuilder()
..addBuilderFactory(
const FullType(BuiltList, [FullType(String)]),
() => ListBuilder<String>(),
)
..addBuilderFactory(
const FullType(BuiltMap, [FullType(String), FullType(String)]),
() => MapBuilder<String, String>(),
)
..addBuilderFactory(
const FullType(BuiltList, [FullType(String)]),
() => ListBuilder<String>(),
)
..addBuilderFactory(
const FullType(BuiltSet, [FullType(Pet)]),
() => SetBuilder<Pet>(),
const FullType(BuiltList, [FullType(User)]),
() => ListBuilder<User>(),
)
..addBuilderFactory(
const FullType(BuiltSet, [FullType(String)]),
() => SetBuilder<String>(),
)
..addBuilderFactory(
const FullType(BuiltSet, [FullType(Pet)]),
() => SetBuilder<Pet>(),
)
..addBuilderFactory(
const FullType(BuiltList, [FullType(Pet)]),
() => ListBuilder<Pet>(),
@@ -139,8 +135,8 @@ Serializers serializers = (_$serializers.toBuilder()
() => MapBuilder<String, int>(),
)
..addBuilderFactory(
const FullType(BuiltList, [FullType(User)]),
() => ListBuilder<User>(),
const FullType(BuiltList, [FullType(String)]),
() => ListBuilder<String>(),
)
..add(const DateSerializer())
..add(Iso8601DateTimeSerializer()))