Skip to content

Commit

Permalink
Merge pull request #1491 from microsoft/feature/smaller-deserialization
Browse files Browse the repository at this point in the history
feature/smaller deserialization
  • Loading branch information
baywet authored Apr 5, 2022
2 parents f336e66 + ea9ed75 commit 83a85f7
Show file tree
Hide file tree
Showing 13 changed files with 26 additions and 26 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed

- Fixed a bug where the generator would not strip the common namespace component id for models. [#1483](https://github.com/microsoft/kiota/issues/1483)
- Simplified field deserialization. [#1490](https://github.com/microsoft/kiota/issues/1490)

## [0.0.21] - 2022-04-01

Expand Down
2 changes: 1 addition & 1 deletion abstractions/java/lib/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ publishing {
publications {
gpr(MavenPublication) {
artifactId 'kiota-abstractions'
version '1.0.30'
version '1.0.31'
from(components.java)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.microsoft.kiota.serialization;

import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Consumer;

import javax.annotation.Nonnull;
/**
Expand All @@ -13,7 +13,7 @@ public interface Parsable {
* @return The deserialization information for this object where each entry is a property key with its deserialization callback.
*/
@Nonnull
<T> Map<String, BiConsumer<T, ParseNode>> getFieldDeserializers();
Map<String, Consumer<ParseNode>> getFieldDeserializers();
/**
* Writes the objects properties to the current writer.
* @param writer The writer to write to.
Expand Down
4 changes: 2 additions & 2 deletions serialization/java/json/lib/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ dependencies {
// This dependency is used internally, and not exposed to consumers on their own compile classpath.
implementation 'com.google.guava:guava:31.1-jre'
api 'com.google.code.gson:gson:2.9.0'
api 'com.microsoft.kiota:kiota-abstractions:1.0.29'
api 'com.microsoft.kiota:kiota-abstractions:1.0.31'
}

publishing {
Expand All @@ -53,7 +53,7 @@ publishing {
publications {
gpr(MavenPublication) {
artifactId 'kiota-serialization-json'
version '1.0.9'
version '1.0.10'
from(components.java)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.function.BiConsumer;
import java.util.function.Consumer;

import com.microsoft.kiota.serialization.ParseNode;
Expand Down Expand Up @@ -251,7 +250,7 @@ public <T extends Enum<T>> EnumSet<T> getEnumSetValue(@Nonnull final Class<T> ta
}
return result;
}
private <T extends Parsable> void assignFieldValues(final T item, final Map<String, BiConsumer<T, ParseNode>> fieldDeserializers) {
private <T extends Parsable> void assignFieldValues(final T item, final Map<String, Consumer<ParseNode>> fieldDeserializers) {
if(currentNode.isJsonObject()) {
if(this.onBeforeAssignFieldValues != null) {
this.onBeforeAssignFieldValues.accept(item);
Expand All @@ -262,14 +261,14 @@ private <T extends Parsable> void assignFieldValues(final T item, final Map<Stri
}
for (final Map.Entry<String, JsonElement> fieldEntry : currentNode.getAsJsonObject().entrySet()) {
final String fieldKey = fieldEntry.getKey();
final BiConsumer<? super T, ParseNode> fieldDeserializer = fieldDeserializers.get(fieldKey);
final Consumer<ParseNode> fieldDeserializer = fieldDeserializers.get(fieldKey);
final JsonElement fieldValue = fieldEntry.getValue();
if(fieldValue.isJsonNull())
continue;
if(fieldDeserializer != null) {
final var onBefore = this.onBeforeAssignFieldValues;
final var onAfter = this.onAfterAssignFieldValues;
fieldDeserializer.accept(item, new JsonParseNode(fieldValue) {{
fieldDeserializer.accept(new JsonParseNode(fieldValue) {{
this.setOnBeforeAssignFieldValues(onBefore);
this.setOnAfterAssignFieldValues(onAfter);
}});
Expand Down
4 changes: 2 additions & 2 deletions src/Kiota.Builder/KiotaBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1019,7 +1019,7 @@ private void CreatePropertiesForModelClass(OpenApiUrlTreeNode currentNode, OpenA
else if(schema?.AllOf?.Any(x => x.IsObject()) ?? false)
CreatePropertiesForModelClass(currentNode, schema.AllOf.Last(x => x.IsObject()), ns, model);
}
private const string FieldDeserializersMethodName = "GetFieldDeserializers<T>";
private const string FieldDeserializersMethodName = "GetFieldDeserializers";
private const string SerializeMethodName = "Serialize";
private const string AdditionalDataPropName = "AdditionalData";
private const string BackingStorePropertyName = "BackingStore";
Expand All @@ -1028,7 +1028,7 @@ private void CreatePropertiesForModelClass(OpenApiUrlTreeNode currentNode, OpenA
private const string ParseNodeInterface = "IParseNode";
internal const string AdditionalHolderInterface = "IAdditionalDataHolder";
internal static void AddSerializationMembers(CodeClass model, bool includeAdditionalProperties, bool usesBackingStore) {
var serializationPropsType = $"IDictionary<string, Action<T, {ParseNodeInterface}>>";
var serializationPropsType = $"IDictionary<string, Action<{ParseNodeInterface}>>";
if(!model.ContainsMember(FieldDeserializersMethodName)) {
var deserializeProp = new CodeMethod {
Name = FieldDeserializersMethodName,
Expand Down
2 changes: 1 addition & 1 deletion src/Kiota.Builder/Refiners/GoRefiner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ private static void CorrectMethodType(CodeMethod currentMethod) {
else if(currentMethod.IsOfKind(CodeMethodKind.Serializer))
currentMethod.Parameters.Where(x => x.Type.Name.Equals("ISerializationWriter")).ToList().ForEach(x => x.Type.Name = "SerializationWriter");
else if(currentMethod.IsOfKind(CodeMethodKind.Deserializer)) {
currentMethod.ReturnType.Name = $"map[string]func(interface{{}}, {conventions.SerializationHash}.ParseNode)(error)";
currentMethod.ReturnType.Name = $"map[string]func({conventions.SerializationHash}.ParseNode)(error)";
currentMethod.Name = "getFieldDeserializers";
} else if(currentMethod.IsOfKind(CodeMethodKind.ClientConstructor, CodeMethodKind.Constructor, CodeMethodKind.RawUrlConstructor)) {
var rawUrlParam = currentMethod.Parameters.OfKind(CodeParameterKind.RawUrl);
Expand Down
4 changes: 2 additions & 2 deletions src/Kiota.Builder/Refiners/JavaRefiner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ private static void AddEnumSetImport(CodeElement currentElement) {
new (x => x is CodeMethod method && method.IsOfKind(CodeMethodKind.RequestExecutor),
"com.microsoft.kiota.serialization", "Parsable", "ParsableFactory"),
new (x => x is CodeMethod method && method.IsOfKind(CodeMethodKind.Deserializer),
"java.util.function", "BiConsumer"),
"java.util.function", "Consumer"),
new (x => x is CodeMethod method && method.IsOfKind(CodeMethodKind.Deserializer),
"java.util", "HashMap", "Map"),
new (x => x is CodeMethod method && method.IsOfKind(CodeMethodKind.ClientConstructor) &&
Expand Down Expand Up @@ -165,7 +165,7 @@ private static void CorrectMethodType(CodeMethod currentMethod) {
x.Type.Name = x.Type.Name[1..];
});
else if(currentMethod.IsOfKind(CodeMethodKind.Deserializer)) {
currentMethod.ReturnType.Name = $"Map<String, BiConsumer<T, ParseNode>>";
currentMethod.ReturnType.Name = $"Map<String, Consumer<ParseNode>>";
currentMethod.Name = "getFieldDeserializers";
}
else if(currentMethod.IsOfKind(CodeMethodKind.ClientConstructor, CodeMethodKind.Constructor, CodeMethodKind.RawUrlConstructor)) {
Expand Down
2 changes: 1 addition & 1 deletion src/Kiota.Builder/Refiners/TypeScriptRefiner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ private static void CorrectMethodType(CodeMethod currentMethod) {
else if(currentMethod.IsOfKind(CodeMethodKind.Serializer))
currentMethod.Parameters.Where(x => x.IsOfKind(CodeParameterKind.Serializer) && x.Type.Name.StartsWith("i", StringComparison.OrdinalIgnoreCase)).ToList().ForEach(x => x.Type.Name = x.Type.Name[1..]);
else if (currentMethod.IsOfKind(CodeMethodKind.Deserializer))
currentMethod.ReturnType.Name = $"Record<string, (item: T, node: ParseNode) => void>";
currentMethod.ReturnType.Name = $"Record<string, (node: ParseNode) => void>";
else if (currentMethod.IsOfKind(CodeMethodKind.ClientConstructor, CodeMethodKind.Constructor))
{
currentMethod.Parameters.Where(x => x.IsOfKind(CodeParameterKind.RequestAdapter, CodeParameterKind.BackingStore))
Expand Down
4 changes: 2 additions & 2 deletions src/Kiota.Builder/Writers/CSharp/CodeMethodWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -177,14 +177,14 @@ private static void AssignPropertyFromParameter(CodeClass parentClass, CodeMetho
private void WriteDeserializerBody(bool shouldHide, CodeMethod codeElement, CodeClass parentClass, LanguageWriter writer)
{
var parentSerializationInfo = shouldHide ? $"(base.{codeElement.Name.ToFirstCharacterUpperCase()}())" : string.Empty;
writer.WriteLine($"return new Dictionary<string, Action<T, {conventions.ParseNodeInterfaceName}>>{parentSerializationInfo} {{");
writer.WriteLine($"return new Dictionary<string, Action<{conventions.ParseNodeInterfaceName}>>{parentSerializationInfo} {{");
writer.IncreaseIndent();
foreach (var otherProp in parentClass
.Properties
.Where(x => x.IsOfKind(CodePropertyKind.Custom))
.OrderBy(x => x.Name))
{
writer.WriteLine($"{{\"{otherProp.SerializationName ?? otherProp.Name.ToFirstCharacterLowerCase()}\", (o,n) => {{ (o as {parentClass.Name.ToFirstCharacterUpperCase()}).{otherProp.Name.ToFirstCharacterUpperCase()} = n.{GetDeserializationMethodName(otherProp.Type, codeElement)}; }} }},");
writer.WriteLine($"{{\"{otherProp.SerializationName ?? otherProp.Name.ToFirstCharacterLowerCase()}\", n => {{ {otherProp.Name.ToFirstCharacterUpperCase()} = n.{GetDeserializationMethodName(otherProp.Type, codeElement)}; }} }},");
}
writer.DecreaseIndent();
writer.WriteLine("};");
Expand Down
2 changes: 1 addition & 1 deletion src/Kiota.Builder/Writers/Go/CodeMethodWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ private void WriteDeserializerBody(CodeMethod codeElement, CodeClass parentClass
writer.WriteLine("return res");
}
private void WriteFieldDeserializer(CodeProperty property, LanguageWriter writer, CodeClass parentClass, string parsableImportSymbol) {
writer.WriteLine($"res[\"{property.SerializationName ?? property.Name.ToFirstCharacterLowerCase()}\"] = func (o interface{{}}, n {parsableImportSymbol}) error {{");
writer.WriteLine($"res[\"{property.SerializationName ?? property.Name.ToFirstCharacterLowerCase()}\"] = func (n {parsableImportSymbol}) error {{");
writer.IncreaseIndent();
var propertyTypeImportName = conventions.GetTypeString(property.Type, parentClass, false, false);
var deserializationMethodName = GetDeserializationMethodName(property.Type, parentClass);
Expand Down
9 changes: 5 additions & 4 deletions src/Kiota.Builder/Writers/Java/CodeMethodWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -220,14 +220,16 @@ private void WriteIndexerBody(CodeMethod codeElement, CodeClass parentClass, Lan
}
private void WriteDeserializerBody(CodeMethod codeElement, CodeMethod method, CodeClass parentClass, LanguageWriter writer, bool inherits) {
var fieldToSerialize = parentClass.GetPropertiesOfKind(CodePropertyKind.Custom);
writer.WriteLine($"return new HashMap<>({(inherits ? "super." + codeElement.Name.ToFirstCharacterLowerCase()+ "()" : fieldToSerialize.Count())}) {{{{");
writer.WriteLines(
$"final {parentClass.Name.ToFirstCharacterUpperCase()} currentObject = this;",
$"return new HashMap<>({(inherits ? "super." + codeElement.Name.ToFirstCharacterLowerCase()+ "()" : fieldToSerialize.Count())}) {{{{");
if(fieldToSerialize.Any()) {
writer.IncreaseIndent();
fieldToSerialize
.OrderBy(x => x.Name)
.Select(x => {
var setterName = x.IsNameEscaped && !string.IsNullOrEmpty(x.SerializationName) ? x.SerializationName : x.Name;
return $"this.put(\"{x.SerializationName ?? x.Name.ToFirstCharacterLowerCase()}\", (o, n) -> {{ (({parentClass.Name.ToFirstCharacterUpperCase()})o).set{setterName.ToFirstCharacterUpperCase()}({GetDeserializationMethodName(x.Type, method)}); }});";
return $"this.put(\"{x.SerializationName ?? x.Name.ToFirstCharacterLowerCase()}\", (n) -> {{ currentObject.set{setterName.ToFirstCharacterUpperCase()}({GetDeserializationMethodName(x.Type, method)}); }});";
})
.ToList()
.ForEach(x => writer.WriteLine(x));
Expand Down Expand Up @@ -348,7 +350,6 @@ private void WriteSerializerBody(CodeClass parentClass, CodeMethod method, Langu
private static readonly CodeParameterOrderComparer parameterOrderComparer = new();
private void WriteMethodPrototype(CodeMethod code, LanguageWriter writer, string returnType) {
var accessModifier = conventions.GetAccessModifier(code.Access);
var genericTypeParameterDeclaration = code.IsOfKind(CodeMethodKind.Deserializer) ? " <T>": string.Empty;
var returnTypeAsyncPrefix = code.IsAsync ? "java.util.concurrent.CompletableFuture<" : string.Empty;
var returnTypeAsyncSuffix = code.IsAsync ? ">" : string.Empty;
var isConstructor = code.IsOfKind(CodeMethodKind.Constructor, CodeMethodKind.ClientConstructor, CodeMethodKind.RawUrlConstructor);
Expand All @@ -366,7 +367,7 @@ private void WriteMethodPrototype(CodeMethod code, LanguageWriter writer, string
returnType;
var finalReturnType = isConstructor ? string.Empty : $" {returnTypeAsyncPrefix}{collectionCorrectedReturnType}{returnTypeAsyncSuffix}";
var staticModifier = code.IsStatic ? " static" : string.Empty;
writer.WriteLine($"{accessModifier}{staticModifier}{genericTypeParameterDeclaration}{finalReturnType} {methodName}({parameters}) {throwableDeclarations}{{");
writer.WriteLine($"{accessModifier}{staticModifier}{finalReturnType} {methodName}({parameters}) {throwableDeclarations}{{");
}
private void WriteMethodDocumentation(CodeMethod code, LanguageWriter writer) {
var isDescriptionPresent = !string.IsNullOrEmpty(code.Description);
Expand Down
7 changes: 3 additions & 4 deletions src/Kiota.Builder/Writers/TypeScript/CodeMethodWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -189,9 +189,8 @@ private static void WriteDefaultMethodBody(CodeMethod codeElement, LanguageWrite
private void WriteDeserializerBody(CodeMethod codeElement, CodeClass parentClass, LanguageWriter writer, bool inherits) {
writer.WriteLine($"return {{{(inherits? $"...super.{codeElement.Name.ToFirstCharacterLowerCase()}(),": string.Empty)}");
writer.IncreaseIndent();
var parentClassName = parentClass.Name.ToFirstCharacterUpperCase();
foreach(var otherProp in parentClass.GetPropertiesOfKind(CodePropertyKind.Custom)) {
writer.WriteLine($"\"{otherProp.SerializationName ?? otherProp.Name.ToFirstCharacterLowerCase()}\": (o, n) => {{ (o as unknown as {parentClassName}).{otherProp.Name.ToFirstCharacterLowerCase()} = n.{GetDeserializationMethodName(otherProp.Type)}; }},");
writer.WriteLine($"\"{otherProp.SerializationName ?? otherProp.Name.ToFirstCharacterLowerCase()}\": n => {{ this.{otherProp.Name.ToFirstCharacterLowerCase()} = n.{GetDeserializationMethodName(otherProp.Type)}; }},");
}
writer.DecreaseIndent();
writer.WriteLine("};");
Expand Down Expand Up @@ -247,9 +246,9 @@ private void WriteRequestGeneratorBody(CodeMethod codeElement, RequestParams req
$"{RequestInfoVarName}.pathParameters = {GetPropertyCall(urlTemplateParamsProperty, "''")};",
$"{RequestInfoVarName}.httpMethod = HttpMethod.{codeElement.HttpMethod.ToString().ToUpperInvariant()};");
if(requestParams.headers != null)
writer.WriteLine($"if(h) {RequestInfoVarName}.headers = h;");
writer.WriteLine($"if({requestParams.headers.Name}) {RequestInfoVarName}.headers = {requestParams.headers.Name};");
if(requestParams.queryString != null)
writer.WriteLines($"{requestParams.queryString.Name} && {RequestInfoVarName}.setQueryStringParametersFromRawObject(q);");
writer.WriteLines($"{requestParams.queryString.Name} && {RequestInfoVarName}.setQueryStringParametersFromRawObject({requestParams.queryString.Name});");
if(requestParams.requestBody != null) {
if(requestParams.requestBody.Type.Name.Equals(localConventions.StreamTypeName, StringComparison.OrdinalIgnoreCase))
writer.WriteLine($"{RequestInfoVarName}.setStreamContent({requestParams.requestBody.Name});");
Expand Down

0 comments on commit 83a85f7

Please sign in to comment.