From f20a839232340eae9699ab905ded0ca6199f5509 Mon Sep 17 00:00:00 2001 From: alzimmermsft <48699787+alzimmermsft@users.noreply.github.com> Date: Fri, 17 May 2024 15:42:46 -0400 Subject: [PATCH 1/6] Limit accessor to parent models only --- .../ConvenienceMethodTemplateBase.java | 12 ++- .../JsonMergePatchHelperTemplate.java | 98 +++++++++---------- .../autorest/template/ModelTemplate.java | 47 +++++---- .../StreamSerializationModelTemplate.java | 4 +- 4 files changed, 83 insertions(+), 78 deletions(-) diff --git a/javagen/src/main/java/com/azure/autorest/template/ConvenienceMethodTemplateBase.java b/javagen/src/main/java/com/azure/autorest/template/ConvenienceMethodTemplateBase.java index 0b0a5c7a32..99a32c77dd 100644 --- a/javagen/src/main/java/com/azure/autorest/template/ConvenienceMethodTemplateBase.java +++ b/javagen/src/main/java/com/azure/autorest/template/ConvenienceMethodTemplateBase.java @@ -784,11 +784,13 @@ private static List getParameters(ClientMethod method, boolean * @return the name of the variable that holds the converted parameter */ private static String writeParameterConversionExpressionWithJsonMergePatchEnabled(JavaBlock javaBlock, String convenientParameterTypeName, String convenientParameterName, String expression) { - String variableName = convenientParameterName + "InBinaryData"; - javaBlock.line(String.format("JsonMergePatchHelper.get%1$sAccessor().prepareModelForJsonMergePatch(%2$s, true);", convenientParameterTypeName, convenientParameterName)); - javaBlock.line(String.format("BinaryData %1$s = BinaryData.fromBytes(%2$s.toBytes());", variableName, expression)); // BinaryData.fromObject() will not fire serialization, use toBytes() to fire serialization - javaBlock.line(String.format("JsonMergePatchHelper.get%1$sAccessor().prepareModelForJsonMergePatch(%2$s, false);", convenientParameterTypeName, convenientParameterName)); - return variableName; + String variableName = convenientParameterName + "InBinaryData"; + javaBlock.line(String.format("JsonMergePatchHelper.get%1$sAccessor().prepareModelForJsonMergePatch(%2$s, true);", convenientParameterTypeName, convenientParameterName)); + javaBlock.line("BinaryData " + variableName + " = " + expression + ";"); + javaBlock.line("// BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization."); + javaBlock.line(variableName + ".getLength();"); + javaBlock.line(String.format("JsonMergePatchHelper.get%1$sAccessor().prepareModelForJsonMergePatch(%2$s, false);", convenientParameterTypeName, convenientParameterName)); + return variableName; } protected static class MethodParameter { diff --git a/javagen/src/main/java/com/azure/autorest/template/JsonMergePatchHelperTemplate.java b/javagen/src/main/java/com/azure/autorest/template/JsonMergePatchHelperTemplate.java index 0edb0c0de5..c3f4ba7a44 100644 --- a/javagen/src/main/java/com/azure/autorest/template/JsonMergePatchHelperTemplate.java +++ b/javagen/src/main/java/com/azure/autorest/template/JsonMergePatchHelperTemplate.java @@ -38,76 +38,68 @@ public void write(List models, JavaFile javaFile) { javaFile.javadocComment(comment -> comment.description("This is the Helper class to enable json merge patch serialization for a model")); // class code - javaFile.publicClass(null, ClientModelUtil.JSON_MERGE_PATCH_HELPER_CLASS_NAME, javaClass -> { - addAccessorProperties(models, javaClass); - addAccessorInterfaces(models, javaClass); - addGettersAndSetters(models, javaClass); - }); + javaFile.publicClass(null, ClientModelUtil.JSON_MERGE_PATCH_HELPER_CLASS_NAME, + javaClass -> createJsonMergePatchAccessHelpers(models, javaClass)); } /** * Add imports for JsonMergePatchHelper. - * @param imports - * @param models - * @param settings + * + * @param imports Set of imports to add to. + * @param models List of models in the service that are used in json-merge-patch. + * @param settings JavaSettings to use. */ private static void addImports(Set imports, List models, JavaSettings settings) { if (models != null && !models.isEmpty()) { - models.forEach(model -> { - model.addImportsTo(imports, settings); - }); + models.forEach(model -> model.addImportsTo(imports, settings)); } } /** - * Add accessor properties for each model that is used in json-merge-patch. + * Creates the access helpers for the json-merge-patch models in a service. + *

+ * This will create the accessor property, interface, and method for each model that is used in json-merge-patch. + * Instead of following standard patterns where all fields are declared together, the field, interface, and static + * methods for each model are declared together. * - * @param models - * @param javaClass + * @param models List of models in the service that are used in json-merge-patch. + * @param javaClass JavaClass to add accessor properties. */ - private static void addAccessorProperties(List models, JavaClass javaClass) { - if (models != null && !models.isEmpty()) { - models.forEach(model -> { - javaClass.privateMemberVariable(String.format("static %sAccessor %sAccessor", model.getName(), CodeNamer.toCamelCase(model.getName()))); - }); + private static void createJsonMergePatchAccessHelpers(List models, JavaClass javaClass) { + if (models == null || models.isEmpty()) { + return; } - } - /** - * Add accessor interfaces for each model that is used in json-merge-patch. - * - * @param models - * @param javaClass - */ - private static void addAccessorInterfaces(List models, JavaClass javaClass) { - if (models != null && !models.isEmpty()) { - models.forEach(model -> { - javaClass.interfaceBlock(JavaVisibility.Public, String.format("%sAccessor", model.getName()), interfaceBlock -> { - interfaceBlock.publicMethod(String.format("%1$s prepareModelForJsonMergePatch(%1$s %2$s, boolean jsonMergePatchEnabled)", model.getName(), CodeNamer.toCamelCase(model.getName()))); - }); - }); - } - } + for (ClientModel model : models) { + if (model.getParentModelName() != null && !model.getParentModelName().isEmpty()) { + // Only polymorphic parent models generate an accessor. + continue; + } + if (!model.getImplementationDetails().isInput()) { + // Model is only used as output and doesn't need to support json-merge-patch. + continue; + } - /** - * Add getter and setter for each model that is used in json-merge-patch. - * - * @param models - * @param javaClass - */ - private static void addGettersAndSetters(List models, JavaClass javaClass) { - if (models != null && !models.isEmpty()) { - models.forEach(model -> { - // setters - javaClass.publicStaticMethod(String.format("void set%1$sAccessor(%1$sAccessor accessor)", model.getName()),methodBlock -> { - methodBlock.line(String.format("%sAccessor = accessor;", CodeNamer.toCamelCase(model.getName()))); - }); - // getters - javaClass.publicStaticMethod(String.format("%1$sAccessor get%1$sAccessor()", model.getName()), methodBlock -> { - methodBlock.methodReturn(String.format("%sAccessor",CodeNamer.toCamelCase(model.getName()))); - }); - }); + String modelName = model.getName(); + String camelModelName = CodeNamer.toCamelCase(modelName); + + // Accessor field declaration. + javaClass.privateMemberVariable(String.format("static %sAccessor %sAccessor", modelName, camelModelName)); + + // Accessor interface declaration. + javaClass.interfaceBlock(JavaVisibility.Public, String.format("%sAccessor", modelName), + interfaceBlock -> interfaceBlock.publicMethod( + String.format("%1$s prepareModelForJsonMergePatch(%1$s %2$s, boolean jsonMergePatchEnabled)", + modelName, camelModelName))); + + // Accessor field setter. + javaClass.publicStaticMethod(String.format("void set%1$sAccessor(%1$sAccessor accessor)", modelName), + methodBlock -> methodBlock.line(camelModelName + "Accessor = accessor;")); + + // Accessor field getter. + javaClass.publicStaticMethod(String.format("%1$sAccessor get%1$sAccessor()", modelName), + methodBlock -> methodBlock.methodReturn(camelModelName + "Accessor")); } } } diff --git a/javagen/src/main/java/com/azure/autorest/template/ModelTemplate.java b/javagen/src/main/java/com/azure/autorest/template/ModelTemplate.java index 574eb79aaf..8bc48d351c 100644 --- a/javagen/src/main/java/com/azure/autorest/template/ModelTemplate.java +++ b/javagen/src/main/java/com/azure/autorest/template/ModelTemplate.java @@ -1255,28 +1255,39 @@ public boolean add(String s) { * Add json-merge-patch related flag and accessors. */ private void addJsonMergePatchRelatedPropertyAndAccessors(JavaClass classBlock, ClientModel model) { - // properties - addGeneratedAnnotation(classBlock); - classBlock.privateMemberVariable("boolean jsonMergePatch"); + if (!model.getImplementationDetails().isInput()) { + // Model doesn't get used in serialization, no need to add json merge patch related properties and + // accessors. + return; + } - classBlock.javadocComment(comment -> { - comment.description("Stores updated model property, the value is property name, not serialized name"); - }); - addGeneratedAnnotation(classBlock); - classBlock.privateFinalMemberVariable("Set updatedProperties = new HashSet<>()"); + // Only the root model needs to have the jsonMergePatch property and accessors. + boolean rootParent = model.getParentModelName() == null || model.getParentModelName().isEmpty(); + if (rootParent) { + // properties + addGeneratedAnnotation(classBlock); + classBlock.privateMemberVariable("boolean jsonMergePatch"); + classBlock.method(JavaVisibility.PackagePrivate, null, "boolean isJsonMergePatch()", + method -> method.line("return this.jsonMergePatch;")); + } - // setter + classBlock.javadocComment(comment -> + comment.description("Stores updated model property, the value is property name, not serialized name")); addGeneratedAnnotation(classBlock); - classBlock.packagePrivateMethod("void serializeAsJsonMergePatch(boolean jsonMergePatch)", method -> { - method.line("this.jsonMergePatch = jsonMergePatch;"); - }); + classBlock.privateFinalMemberVariable("Set updatedProperties = new HashSet<>()"); - // static code block to access jsonMergePatch setter - classBlock.staticBlock(staticBlock -> { - staticBlock.text(String.format("JsonMergePatchHelper.set%sAccessor((model, jsonMergePatchEnabled) -> {\n" + - "model.serializeAsJsonMergePatch(jsonMergePatchEnabled);\n" + - "return model;\n" + "});", model.getName())); - }); + if (rootParent) { + // setter + addGeneratedAnnotation(classBlock); + classBlock.privateMethod("void serializeAsJsonMergePatch(boolean jsonMergePatch)", + method -> method.line("this.jsonMergePatch = jsonMergePatch;")); + + // static code block to access jsonMergePatch setter + classBlock.staticBlock(staticBlock -> staticBlock.text(String.format( + "JsonMergePatchHelper.set%sAccessor((model, jsonMergePatchEnabled) -> {\n" + + "model.serializeAsJsonMergePatch(jsonMergePatchEnabled);\n" + "return model;\n" + "});", + model.getName()))); + } } private static boolean modelDefinesProperty(ClientModel model, ClientModelProperty property) { diff --git a/javagen/src/main/java/com/azure/autorest/template/StreamSerializationModelTemplate.java b/javagen/src/main/java/com/azure/autorest/template/StreamSerializationModelTemplate.java index cb3e07d13b..a8680f9d50 100644 --- a/javagen/src/main/java/com/azure/autorest/template/StreamSerializationModelTemplate.java +++ b/javagen/src/main/java/com/azure/autorest/template/StreamSerializationModelTemplate.java @@ -242,8 +242,8 @@ private static void writeToJson(JavaClass classBlock, ClientModelPropertiesManag classBlock.annotation("Override"); classBlock.publicMethod("JsonWriter toJson(JsonWriter jsonWriter) throws IOException", methodBlock -> { if (isJsonMergePatch) { - methodBlock.ifBlock("jsonMergePatch", ifBlock -> ifBlock.methodReturn("toJsonMergePatch(jsonWriter)")) - .elseBlock(elseBlock -> serializeJsonProperties(methodBlock, propertiesManager, false)); + methodBlock.ifBlock("isJsonMergePatch()", ifBlock -> ifBlock.methodReturn("toJsonMergePatch(jsonWriter)")) + .elseBlock(elseBlock -> serializeJsonProperties(methodBlock, propertiesManager, false)); } else { serializeJsonProperties(methodBlock, propertiesManager, false); } From 8a5f13e1157f9b5714efe0c71e952bf45b814d99 Mon Sep 17 00:00:00 2001 From: alzimmermsft <48699787+alzimmermsft@users.noreply.github.com> Date: Fri, 17 May 2024 16:14:20 -0400 Subject: [PATCH 2/6] Regenerate using simplified accessor pattern --- .../autorest/template/ModelTemplate.java | 2 + .../azure/core/basic/BasicAsyncClient.java | 4 +- .../_specs_/azure/core/basic/BasicClient.java | 4 +- .../implementation/JsonMergePatchHelper.java | 12 +-- .../_specs_/azure/core/basic/models/User.java | 9 ++- .../azure/core/basic/models/UserOrder.java | 9 ++- .../com/cadl/flatten/FlattenAsyncClient.java | 4 +- .../java/com/cadl/flatten/FlattenClient.java | 4 +- .../implementation/JsonMergePatchHelper.java | 12 +-- .../cadl/flatten/models/TodoItemPatch.java | 9 ++- .../flatten/models/UpdatePatchRequest.java | 9 ++- .../java/com/cadl/patch/PatchAsyncClient.java | 12 ++- .../main/java/com/cadl/patch/PatchClient.java | 12 ++- .../implementation/JsonMergePatchHelper.java | 54 +++---------- .../main/java/com/cadl/patch/models/Fish.java | 9 ++- .../com/cadl/patch/models/InnerModel.java | 9 ++- .../java/com/cadl/patch/models/Resource.java | 9 ++- .../java/com/cadl/patch/models/Salmon.java | 17 +--- .../java/com/cadl/patch/models/Shark.java | 18 +---- .../EtagHeadersAsyncClient.java | 8 +- .../specialheaders/EtagHeadersClient.java | 8 +- .../RepeatabilityHeadersAsyncClient.java | 4 +- .../RepeatabilityHeadersClient.java | 4 +- .../cadl/specialheaders/models/Resource.java | 9 ++- .../JsonMergePatchAsyncClient.java | 8 +- .../jsonmergepatch/JsonMergePatchClient.java | 8 +- .../implementation/JsonMergePatchHelper.java | 12 +-- .../jsonmergepatch/models/InnerModel.java | 9 ++- .../jsonmergepatch/models/ResourcePatch.java | 9 ++- .../property/nullable/BytesAsyncClient.java | 8 +- .../type/property/nullable/BytesClient.java | 8 +- .../nullable/CollectionsByteAsyncClient.java | 8 +- .../nullable/CollectionsByteClient.java | 8 +- .../nullable/CollectionsModelAsyncClient.java | 8 +- .../nullable/CollectionsModelClient.java | 8 +- .../DatetimeOperationAsyncClient.java | 8 +- .../nullable/DatetimeOperationClient.java | 8 +- .../DurationOperationAsyncClient.java | 8 +- .../nullable/DurationOperationClient.java | 8 +- .../nullable/StringOperationAsyncClient.java | 8 +- .../nullable/StringOperationClient.java | 8 +- .../implementation/JsonMergePatchHelper.java | 80 +++++++++---------- .../nullable/models/BytesProperty.java | 9 ++- .../models/CollectionsByteProperty.java | 9 ++- .../models/CollectionsModelProperty.java | 9 ++- .../nullable/models/DatetimeProperty.java | 9 ++- .../nullable/models/DurationProperty.java | 9 ++- .../property/nullable/models/InnerModel.java | 9 ++- .../nullable/models/StringProperty.java | 9 ++- 49 files changed, 325 insertions(+), 211 deletions(-) diff --git a/javagen/src/main/java/com/azure/autorest/template/ModelTemplate.java b/javagen/src/main/java/com/azure/autorest/template/ModelTemplate.java index 8bc48d351c..c5f09a7970 100644 --- a/javagen/src/main/java/com/azure/autorest/template/ModelTemplate.java +++ b/javagen/src/main/java/com/azure/autorest/template/ModelTemplate.java @@ -1267,6 +1267,8 @@ private void addJsonMergePatchRelatedPropertyAndAccessors(JavaClass classBlock, // properties addGeneratedAnnotation(classBlock); classBlock.privateMemberVariable("boolean jsonMergePatch"); + + addGeneratedAnnotation(classBlock); classBlock.method(JavaVisibility.PackagePrivate, null, "boolean isJsonMergePatch()", method -> method.line("return this.jsonMergePatch;")); } diff --git a/typespec-tests/src/main/java/com/_specs_/azure/core/basic/BasicAsyncClient.java b/typespec-tests/src/main/java/com/_specs_/azure/core/basic/BasicAsyncClient.java index da8c688f25..df0a5187a0 100644 --- a/typespec-tests/src/main/java/com/_specs_/azure/core/basic/BasicAsyncClient.java +++ b/typespec-tests/src/main/java/com/_specs_/azure/core/basic/BasicAsyncClient.java @@ -429,7 +429,9 @@ public Mono createOrUpdate(int id, User resource) { // Generated convenience method for createOrUpdateWithResponse RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getUserAccessor().prepareModelForJsonMergePatch(resource, true); - BinaryData resourceInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(resource).toBytes()); + BinaryData resourceInBinaryData = BinaryData.fromObject(resource); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + resourceInBinaryData.getLength(); JsonMergePatchHelper.getUserAccessor().prepareModelForJsonMergePatch(resource, false); return createOrUpdateWithResponse(id, resourceInBinaryData, requestOptions).flatMap(FluxUtil::toMono) .map(protocolMethodData -> protocolMethodData.toObject(User.class)); diff --git a/typespec-tests/src/main/java/com/_specs_/azure/core/basic/BasicClient.java b/typespec-tests/src/main/java/com/_specs_/azure/core/basic/BasicClient.java index b790b5d259..44c324b815 100644 --- a/typespec-tests/src/main/java/com/_specs_/azure/core/basic/BasicClient.java +++ b/typespec-tests/src/main/java/com/_specs_/azure/core/basic/BasicClient.java @@ -422,7 +422,9 @@ public User createOrUpdate(int id, User resource) { // Generated convenience method for createOrUpdateWithResponse RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getUserAccessor().prepareModelForJsonMergePatch(resource, true); - BinaryData resourceInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(resource).toBytes()); + BinaryData resourceInBinaryData = BinaryData.fromObject(resource); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + resourceInBinaryData.getLength(); JsonMergePatchHelper.getUserAccessor().prepareModelForJsonMergePatch(resource, false); return createOrUpdateWithResponse(id, resourceInBinaryData, requestOptions).getValue().toObject(User.class); } diff --git a/typespec-tests/src/main/java/com/_specs_/azure/core/basic/implementation/JsonMergePatchHelper.java b/typespec-tests/src/main/java/com/_specs_/azure/core/basic/implementation/JsonMergePatchHelper.java index 399c8f4afa..c57946cee0 100644 --- a/typespec-tests/src/main/java/com/_specs_/azure/core/basic/implementation/JsonMergePatchHelper.java +++ b/typespec-tests/src/main/java/com/_specs_/azure/core/basic/implementation/JsonMergePatchHelper.java @@ -13,16 +13,10 @@ public class JsonMergePatchHelper { private static UserAccessor userAccessor; - private static UserOrderAccessor userOrderAccessor; - public interface UserAccessor { User prepareModelForJsonMergePatch(User user, boolean jsonMergePatchEnabled); } - public interface UserOrderAccessor { - UserOrder prepareModelForJsonMergePatch(UserOrder userOrder, boolean jsonMergePatchEnabled); - } - public static void setUserAccessor(UserAccessor accessor) { userAccessor = accessor; } @@ -31,6 +25,12 @@ public static UserAccessor getUserAccessor() { return userAccessor; } + private static UserOrderAccessor userOrderAccessor; + + public interface UserOrderAccessor { + UserOrder prepareModelForJsonMergePatch(UserOrder userOrder, boolean jsonMergePatchEnabled); + } + public static void setUserOrderAccessor(UserOrderAccessor accessor) { userOrderAccessor = accessor; } diff --git a/typespec-tests/src/main/java/com/_specs_/azure/core/basic/models/User.java b/typespec-tests/src/main/java/com/_specs_/azure/core/basic/models/User.java index ce4a45f53f..1d4333c048 100644 --- a/typespec-tests/src/main/java/com/_specs_/azure/core/basic/models/User.java +++ b/typespec-tests/src/main/java/com/_specs_/azure/core/basic/models/User.java @@ -48,6 +48,11 @@ public final class User implements JsonSerializable { @Generated private boolean jsonMergePatch; + @Generated + boolean isJsonMergePatch() { + return this.jsonMergePatch; + } + /** * Stores updated model property, the value is property name, not serialized name. */ @@ -55,7 +60,7 @@ public final class User implements JsonSerializable { private final Set updatedProperties = new HashSet<>(); @Generated - void serializeAsJsonMergePatch(boolean jsonMergePatch) { + private void serializeAsJsonMergePatch(boolean jsonMergePatch) { this.jsonMergePatch = jsonMergePatch; } @@ -146,7 +151,7 @@ public String getEtag() { @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (jsonMergePatch) { + if (isJsonMergePatch()) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); diff --git a/typespec-tests/src/main/java/com/_specs_/azure/core/basic/models/UserOrder.java b/typespec-tests/src/main/java/com/_specs_/azure/core/basic/models/UserOrder.java index cd3dee8165..231a2481ee 100644 --- a/typespec-tests/src/main/java/com/_specs_/azure/core/basic/models/UserOrder.java +++ b/typespec-tests/src/main/java/com/_specs_/azure/core/basic/models/UserOrder.java @@ -41,6 +41,11 @@ public final class UserOrder implements JsonSerializable { @Generated private boolean jsonMergePatch; + @Generated + boolean isJsonMergePatch() { + return this.jsonMergePatch; + } + /** * Stores updated model property, the value is property name, not serialized name. */ @@ -48,7 +53,7 @@ public final class UserOrder implements JsonSerializable { private final Set updatedProperties = new HashSet<>(); @Generated - void serializeAsJsonMergePatch(boolean jsonMergePatch) { + private void serializeAsJsonMergePatch(boolean jsonMergePatch) { this.jsonMergePatch = jsonMergePatch; } @@ -130,7 +135,7 @@ public UserOrder setDetail(String detail) { @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (jsonMergePatch) { + if (isJsonMergePatch()) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); diff --git a/typespec-tests/src/main/java/com/cadl/flatten/FlattenAsyncClient.java b/typespec-tests/src/main/java/com/cadl/flatten/FlattenAsyncClient.java index 387ebe6fc0..56e00aa831 100644 --- a/typespec-tests/src/main/java/com/cadl/flatten/FlattenAsyncClient.java +++ b/typespec-tests/src/main/java/com/cadl/flatten/FlattenAsyncClient.java @@ -358,7 +358,9 @@ public Mono update(long id, UpdatePatchRequest request) { // Generated convenience method for updateWithResponse RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getUpdatePatchRequestAccessor().prepareModelForJsonMergePatch(request, true); - BinaryData requestInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(request).toBytes()); + BinaryData requestInBinaryData = BinaryData.fromObject(request); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + requestInBinaryData.getLength(); JsonMergePatchHelper.getUpdatePatchRequestAccessor().prepareModelForJsonMergePatch(request, false); return updateWithResponse(id, requestInBinaryData, requestOptions).flatMap(FluxUtil::toMono) .map(protocolMethodData -> protocolMethodData.toObject(TodoItem.class)); diff --git a/typespec-tests/src/main/java/com/cadl/flatten/FlattenClient.java b/typespec-tests/src/main/java/com/cadl/flatten/FlattenClient.java index b966eb5cb8..08c5372dd0 100644 --- a/typespec-tests/src/main/java/com/cadl/flatten/FlattenClient.java +++ b/typespec-tests/src/main/java/com/cadl/flatten/FlattenClient.java @@ -351,7 +351,9 @@ public TodoItem update(long id, UpdatePatchRequest request) { // Generated convenience method for updateWithResponse RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getUpdatePatchRequestAccessor().prepareModelForJsonMergePatch(request, true); - BinaryData requestInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(request).toBytes()); + BinaryData requestInBinaryData = BinaryData.fromObject(request); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + requestInBinaryData.getLength(); JsonMergePatchHelper.getUpdatePatchRequestAccessor().prepareModelForJsonMergePatch(request, false); return updateWithResponse(id, requestInBinaryData, requestOptions).getValue().toObject(TodoItem.class); } diff --git a/typespec-tests/src/main/java/com/cadl/flatten/implementation/JsonMergePatchHelper.java b/typespec-tests/src/main/java/com/cadl/flatten/implementation/JsonMergePatchHelper.java index aabdf94b6b..4a318ec2da 100644 --- a/typespec-tests/src/main/java/com/cadl/flatten/implementation/JsonMergePatchHelper.java +++ b/typespec-tests/src/main/java/com/cadl/flatten/implementation/JsonMergePatchHelper.java @@ -13,17 +13,11 @@ public class JsonMergePatchHelper { private static UpdatePatchRequestAccessor updatePatchRequestAccessor; - private static TodoItemPatchAccessor todoItemPatchAccessor; - public interface UpdatePatchRequestAccessor { UpdatePatchRequest prepareModelForJsonMergePatch(UpdatePatchRequest updatePatchRequest, boolean jsonMergePatchEnabled); } - public interface TodoItemPatchAccessor { - TodoItemPatch prepareModelForJsonMergePatch(TodoItemPatch todoItemPatch, boolean jsonMergePatchEnabled); - } - public static void setUpdatePatchRequestAccessor(UpdatePatchRequestAccessor accessor) { updatePatchRequestAccessor = accessor; } @@ -32,6 +26,12 @@ public static UpdatePatchRequestAccessor getUpdatePatchRequestAccessor() { return updatePatchRequestAccessor; } + private static TodoItemPatchAccessor todoItemPatchAccessor; + + public interface TodoItemPatchAccessor { + TodoItemPatch prepareModelForJsonMergePatch(TodoItemPatch todoItemPatch, boolean jsonMergePatchEnabled); + } + public static void setTodoItemPatchAccessor(TodoItemPatchAccessor accessor) { todoItemPatchAccessor = accessor; } diff --git a/typespec-tests/src/main/java/com/cadl/flatten/models/TodoItemPatch.java b/typespec-tests/src/main/java/com/cadl/flatten/models/TodoItemPatch.java index d14ef9636a..0f376587b8 100644 --- a/typespec-tests/src/main/java/com/cadl/flatten/models/TodoItemPatch.java +++ b/typespec-tests/src/main/java/com/cadl/flatten/models/TodoItemPatch.java @@ -41,6 +41,11 @@ public final class TodoItemPatch implements JsonSerializable { @Generated private boolean jsonMergePatch; + @Generated + boolean isJsonMergePatch() { + return this.jsonMergePatch; + } + /** * Stores updated model property, the value is property name, not serialized name. */ @@ -48,7 +53,7 @@ public final class TodoItemPatch implements JsonSerializable { private final Set updatedProperties = new HashSet<>(); @Generated - void serializeAsJsonMergePatch(boolean jsonMergePatch) { + private void serializeAsJsonMergePatch(boolean jsonMergePatch) { this.jsonMergePatch = jsonMergePatch; } @@ -141,7 +146,7 @@ public TodoItemPatch setStatus(TodoItemPatchStatus status) { @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (jsonMergePatch) { + if (isJsonMergePatch()) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); diff --git a/typespec-tests/src/main/java/com/cadl/flatten/models/UpdatePatchRequest.java b/typespec-tests/src/main/java/com/cadl/flatten/models/UpdatePatchRequest.java index 8afa5ba5b9..9837112532 100644 --- a/typespec-tests/src/main/java/com/cadl/flatten/models/UpdatePatchRequest.java +++ b/typespec-tests/src/main/java/com/cadl/flatten/models/UpdatePatchRequest.java @@ -29,6 +29,11 @@ public final class UpdatePatchRequest implements JsonSerializable updatedProperties = new HashSet<>(); @Generated - void serializeAsJsonMergePatch(boolean jsonMergePatch) { + private void serializeAsJsonMergePatch(boolean jsonMergePatch) { this.jsonMergePatch = jsonMergePatch; } @@ -84,7 +89,7 @@ public UpdatePatchRequest setPatch(TodoItemPatch patch) { @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (jsonMergePatch) { + if (isJsonMergePatch()) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); diff --git a/typespec-tests/src/main/java/com/cadl/patch/PatchAsyncClient.java b/typespec-tests/src/main/java/com/cadl/patch/PatchAsyncClient.java index f0b7f8c71a..82d94d0c60 100644 --- a/typespec-tests/src/main/java/com/cadl/patch/PatchAsyncClient.java +++ b/typespec-tests/src/main/java/com/cadl/patch/PatchAsyncClient.java @@ -251,7 +251,9 @@ public Mono createOrUpdateResource(Resource resource) { // Generated convenience method for createOrUpdateResourceWithResponse RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getResourceAccessor().prepareModelForJsonMergePatch(resource, true); - BinaryData resourceInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(resource).toBytes()); + BinaryData resourceInBinaryData = BinaryData.fromObject(resource); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + resourceInBinaryData.getLength(); JsonMergePatchHelper.getResourceAccessor().prepareModelForJsonMergePatch(resource, false); return createOrUpdateResourceWithResponse(resourceInBinaryData, requestOptions).flatMap(FluxUtil::toMono) .map(protocolMethodData -> protocolMethodData.toObject(Resource.class)); @@ -276,7 +278,9 @@ public Mono createOrUpdateOptionalResource(Resource resource) { RequestOptions requestOptions = new RequestOptions(); if (resource != null) { JsonMergePatchHelper.getResourceAccessor().prepareModelForJsonMergePatch(resource, true); - BinaryData resourceInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(resource).toBytes()); + BinaryData resourceInBinaryData = BinaryData.fromObject(resource); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + resourceInBinaryData.getLength(); JsonMergePatchHelper.getResourceAccessor().prepareModelForJsonMergePatch(resource, false); requestOptions.setBody(resourceInBinaryData); } @@ -322,7 +326,9 @@ public Mono createOrUpdateFish(Fish fish) { // Generated convenience method for createOrUpdateFishWithResponse RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getFishAccessor().prepareModelForJsonMergePatch(fish, true); - BinaryData fishInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(fish).toBytes()); + BinaryData fishInBinaryData = BinaryData.fromObject(fish); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + fishInBinaryData.getLength(); JsonMergePatchHelper.getFishAccessor().prepareModelForJsonMergePatch(fish, false); return createOrUpdateFishWithResponse(fishInBinaryData, requestOptions).flatMap(FluxUtil::toMono) .map(protocolMethodData -> protocolMethodData.toObject(Fish.class)); diff --git a/typespec-tests/src/main/java/com/cadl/patch/PatchClient.java b/typespec-tests/src/main/java/com/cadl/patch/PatchClient.java index c84a6706ff..c5f510f214 100644 --- a/typespec-tests/src/main/java/com/cadl/patch/PatchClient.java +++ b/typespec-tests/src/main/java/com/cadl/patch/PatchClient.java @@ -248,7 +248,9 @@ public Resource createOrUpdateResource(Resource resource) { // Generated convenience method for createOrUpdateResourceWithResponse RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getResourceAccessor().prepareModelForJsonMergePatch(resource, true); - BinaryData resourceInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(resource).toBytes()); + BinaryData resourceInBinaryData = BinaryData.fromObject(resource); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + resourceInBinaryData.getLength(); JsonMergePatchHelper.getResourceAccessor().prepareModelForJsonMergePatch(resource, false); return createOrUpdateResourceWithResponse(resourceInBinaryData, requestOptions).getValue() .toObject(Resource.class); @@ -273,7 +275,9 @@ public Resource createOrUpdateOptionalResource(Resource resource) { RequestOptions requestOptions = new RequestOptions(); if (resource != null) { JsonMergePatchHelper.getResourceAccessor().prepareModelForJsonMergePatch(resource, true); - BinaryData resourceInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(resource).toBytes()); + BinaryData resourceInBinaryData = BinaryData.fromObject(resource); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + resourceInBinaryData.getLength(); JsonMergePatchHelper.getResourceAccessor().prepareModelForJsonMergePatch(resource, false); requestOptions.setBody(resourceInBinaryData); } @@ -316,7 +320,9 @@ public Fish createOrUpdateFish(Fish fish) { // Generated convenience method for createOrUpdateFishWithResponse RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getFishAccessor().prepareModelForJsonMergePatch(fish, true); - BinaryData fishInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(fish).toBytes()); + BinaryData fishInBinaryData = BinaryData.fromObject(fish); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + fishInBinaryData.getLength(); JsonMergePatchHelper.getFishAccessor().prepareModelForJsonMergePatch(fish, false); return createOrUpdateFishWithResponse(fishInBinaryData, requestOptions).getValue().toObject(Fish.class); } diff --git a/typespec-tests/src/main/java/com/cadl/patch/implementation/JsonMergePatchHelper.java b/typespec-tests/src/main/java/com/cadl/patch/implementation/JsonMergePatchHelper.java index 3a13ac1c10..931275d2e4 100644 --- a/typespec-tests/src/main/java/com/cadl/patch/implementation/JsonMergePatchHelper.java +++ b/typespec-tests/src/main/java/com/cadl/patch/implementation/JsonMergePatchHelper.java @@ -7,8 +7,6 @@ import com.cadl.patch.models.Fish; import com.cadl.patch.models.InnerModel; import com.cadl.patch.models.Resource; -import com.cadl.patch.models.Salmon; -import com.cadl.patch.models.Shark; /** * This is the Helper class to enable json merge patch serialization for a model. @@ -16,34 +14,10 @@ public class JsonMergePatchHelper { private static ResourceAccessor resourceAccessor; - private static InnerModelAccessor innerModelAccessor; - - private static FishAccessor fishAccessor; - - private static SharkAccessor sharkAccessor; - - private static SalmonAccessor salmonAccessor; - public interface ResourceAccessor { Resource prepareModelForJsonMergePatch(Resource resource, boolean jsonMergePatchEnabled); } - public interface InnerModelAccessor { - InnerModel prepareModelForJsonMergePatch(InnerModel innerModel, boolean jsonMergePatchEnabled); - } - - public interface FishAccessor { - Fish prepareModelForJsonMergePatch(Fish fish, boolean jsonMergePatchEnabled); - } - - public interface SharkAccessor { - Shark prepareModelForJsonMergePatch(Shark shark, boolean jsonMergePatchEnabled); - } - - public interface SalmonAccessor { - Salmon prepareModelForJsonMergePatch(Salmon salmon, boolean jsonMergePatchEnabled); - } - public static void setResourceAccessor(ResourceAccessor accessor) { resourceAccessor = accessor; } @@ -52,6 +26,12 @@ public static ResourceAccessor getResourceAccessor() { return resourceAccessor; } + private static InnerModelAccessor innerModelAccessor; + + public interface InnerModelAccessor { + InnerModel prepareModelForJsonMergePatch(InnerModel innerModel, boolean jsonMergePatchEnabled); + } + public static void setInnerModelAccessor(InnerModelAccessor accessor) { innerModelAccessor = accessor; } @@ -60,6 +40,12 @@ public static InnerModelAccessor getInnerModelAccessor() { return innerModelAccessor; } + private static FishAccessor fishAccessor; + + public interface FishAccessor { + Fish prepareModelForJsonMergePatch(Fish fish, boolean jsonMergePatchEnabled); + } + public static void setFishAccessor(FishAccessor accessor) { fishAccessor = accessor; } @@ -67,20 +53,4 @@ public static void setFishAccessor(FishAccessor accessor) { public static FishAccessor getFishAccessor() { return fishAccessor; } - - public static void setSharkAccessor(SharkAccessor accessor) { - sharkAccessor = accessor; - } - - public static SharkAccessor getSharkAccessor() { - return sharkAccessor; - } - - public static void setSalmonAccessor(SalmonAccessor accessor) { - salmonAccessor = accessor; - } - - public static SalmonAccessor getSalmonAccessor() { - return salmonAccessor; - } } diff --git a/typespec-tests/src/main/java/com/cadl/patch/models/Fish.java b/typespec-tests/src/main/java/com/cadl/patch/models/Fish.java index db0480e59d..110a9cf6ef 100644 --- a/typespec-tests/src/main/java/com/cadl/patch/models/Fish.java +++ b/typespec-tests/src/main/java/com/cadl/patch/models/Fish.java @@ -53,6 +53,11 @@ public class Fish implements JsonSerializable { @Generated private boolean jsonMergePatch; + @Generated + boolean isJsonMergePatch() { + return this.jsonMergePatch; + } + /** * Stores updated model property, the value is property name, not serialized name. */ @@ -60,7 +65,7 @@ public class Fish implements JsonSerializable { private final Set updatedProperties = new HashSet<>(); @Generated - void serializeAsJsonMergePatch(boolean jsonMergePatch) { + private void serializeAsJsonMergePatch(boolean jsonMergePatch) { this.jsonMergePatch = jsonMergePatch; } @@ -189,7 +194,7 @@ public Fish setColor(String color) { @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (jsonMergePatch) { + if (isJsonMergePatch()) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); diff --git a/typespec-tests/src/main/java/com/cadl/patch/models/InnerModel.java b/typespec-tests/src/main/java/com/cadl/patch/models/InnerModel.java index c48a55b913..66c0a2eba1 100644 --- a/typespec-tests/src/main/java/com/cadl/patch/models/InnerModel.java +++ b/typespec-tests/src/main/java/com/cadl/patch/models/InnerModel.java @@ -35,6 +35,11 @@ public final class InnerModel implements JsonSerializable { @Generated private boolean jsonMergePatch; + @Generated + boolean isJsonMergePatch() { + return this.jsonMergePatch; + } + /** * Stores updated model property, the value is property name, not serialized name. */ @@ -42,7 +47,7 @@ public final class InnerModel implements JsonSerializable { private final Set updatedProperties = new HashSet<>(); @Generated - void serializeAsJsonMergePatch(boolean jsonMergePatch) { + private void serializeAsJsonMergePatch(boolean jsonMergePatch) { this.jsonMergePatch = jsonMergePatch; } @@ -113,7 +118,7 @@ public InnerModel setDescription(String description) { @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (jsonMergePatch) { + if (isJsonMergePatch()) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); diff --git a/typespec-tests/src/main/java/com/cadl/patch/models/Resource.java b/typespec-tests/src/main/java/com/cadl/patch/models/Resource.java index 1ba4e96526..2e5cd231e3 100644 --- a/typespec-tests/src/main/java/com/cadl/patch/models/Resource.java +++ b/typespec-tests/src/main/java/com/cadl/patch/models/Resource.java @@ -85,6 +85,11 @@ public final class Resource implements JsonSerializable { @Generated private boolean jsonMergePatch; + @Generated + boolean isJsonMergePatch() { + return this.jsonMergePatch; + } + /** * Stores updated model property, the value is property name, not serialized name. */ @@ -92,7 +97,7 @@ public final class Resource implements JsonSerializable { private final Set updatedProperties = new HashSet<>(); @Generated - void serializeAsJsonMergePatch(boolean jsonMergePatch) { + private void serializeAsJsonMergePatch(boolean jsonMergePatch) { this.jsonMergePatch = jsonMergePatch; } @@ -321,7 +326,7 @@ public Resource setFish(Fish fish) { @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (jsonMergePatch) { + if (isJsonMergePatch()) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); diff --git a/typespec-tests/src/main/java/com/cadl/patch/models/Salmon.java b/typespec-tests/src/main/java/com/cadl/patch/models/Salmon.java index 5b7986ab13..6d4d2598b0 100644 --- a/typespec-tests/src/main/java/com/cadl/patch/models/Salmon.java +++ b/typespec-tests/src/main/java/com/cadl/patch/models/Salmon.java @@ -46,27 +46,12 @@ public final class Salmon extends Fish { @Generated private Fish partner; - @Generated - private boolean jsonMergePatch; - /** * Stores updated model property, the value is property name, not serialized name. */ @Generated private final Set updatedProperties = new HashSet<>(); - @Generated - void serializeAsJsonMergePatch(boolean jsonMergePatch) { - this.jsonMergePatch = jsonMergePatch; - } - - static { - JsonMergePatchHelper.setSalmonAccessor((model, jsonMergePatchEnabled) -> { - model.serializeAsJsonMergePatch(jsonMergePatchEnabled); - return model; - }); - } - /** * Creates an instance of Salmon class. */ @@ -183,7 +168,7 @@ public Salmon setColor(String color) { @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (jsonMergePatch) { + if (isJsonMergePatch()) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); diff --git a/typespec-tests/src/main/java/com/cadl/patch/models/Shark.java b/typespec-tests/src/main/java/com/cadl/patch/models/Shark.java index d9cad26df6..cb2b8d4d87 100644 --- a/typespec-tests/src/main/java/com/cadl/patch/models/Shark.java +++ b/typespec-tests/src/main/java/com/cadl/patch/models/Shark.java @@ -9,7 +9,6 @@ import com.azure.json.JsonReader; import com.azure.json.JsonToken; import com.azure.json.JsonWriter; -import com.cadl.patch.implementation.JsonMergePatchHelper; import java.io.IOException; import java.util.HashSet; import java.util.Set; @@ -25,27 +24,12 @@ public final class Shark extends Fish { @Generated private String kind = "shark"; - @Generated - private boolean jsonMergePatch; - /** * Stores updated model property, the value is property name, not serialized name. */ @Generated private final Set updatedProperties = new HashSet<>(); - @Generated - void serializeAsJsonMergePatch(boolean jsonMergePatch) { - this.jsonMergePatch = jsonMergePatch; - } - - static { - JsonMergePatchHelper.setSharkAccessor((model, jsonMergePatchEnabled) -> { - model.serializeAsJsonMergePatch(jsonMergePatchEnabled); - return model; - }); - } - /** * Creates an instance of Shark class. */ @@ -93,7 +77,7 @@ public Shark setColor(String color) { @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (jsonMergePatch) { + if (isJsonMergePatch()) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); diff --git a/typespec-tests/src/main/java/com/cadl/specialheaders/EtagHeadersAsyncClient.java b/typespec-tests/src/main/java/com/cadl/specialheaders/EtagHeadersAsyncClient.java index 65c2041d8a..4eac256d90 100644 --- a/typespec-tests/src/main/java/com/cadl/specialheaders/EtagHeadersAsyncClient.java +++ b/typespec-tests/src/main/java/com/cadl/specialheaders/EtagHeadersAsyncClient.java @@ -272,7 +272,9 @@ public Mono patchWithMatchHeaders(String name, Resource resource, Matc requestOptions.setHeader(HttpHeaderName.IF_NONE_MATCH, ifNoneMatch); } JsonMergePatchHelper.getResourceAccessor().prepareModelForJsonMergePatch(resource, true); - BinaryData resourceInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(resource).toBytes()); + BinaryData resourceInBinaryData = BinaryData.fromObject(resource); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + resourceInBinaryData.getLength(); JsonMergePatchHelper.getResourceAccessor().prepareModelForJsonMergePatch(resource, false); return patchWithMatchHeadersWithResponse(name, resourceInBinaryData, requestOptions).flatMap(FluxUtil::toMono) .map(protocolMethodData -> protocolMethodData.toObject(Resource.class)); @@ -297,7 +299,9 @@ public Mono patchWithMatchHeaders(String name, Resource resource) { // Generated convenience method for patchWithMatchHeadersWithResponse RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getResourceAccessor().prepareModelForJsonMergePatch(resource, true); - BinaryData resourceInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(resource).toBytes()); + BinaryData resourceInBinaryData = BinaryData.fromObject(resource); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + resourceInBinaryData.getLength(); JsonMergePatchHelper.getResourceAccessor().prepareModelForJsonMergePatch(resource, false); return patchWithMatchHeadersWithResponse(name, resourceInBinaryData, requestOptions).flatMap(FluxUtil::toMono) .map(protocolMethodData -> protocolMethodData.toObject(Resource.class)); diff --git a/typespec-tests/src/main/java/com/cadl/specialheaders/EtagHeadersClient.java b/typespec-tests/src/main/java/com/cadl/specialheaders/EtagHeadersClient.java index be0373dd45..691e9e76fd 100644 --- a/typespec-tests/src/main/java/com/cadl/specialheaders/EtagHeadersClient.java +++ b/typespec-tests/src/main/java/com/cadl/specialheaders/EtagHeadersClient.java @@ -264,7 +264,9 @@ public Resource patchWithMatchHeaders(String name, Resource resource, MatchCondi requestOptions.setHeader(HttpHeaderName.IF_NONE_MATCH, ifNoneMatch); } JsonMergePatchHelper.getResourceAccessor().prepareModelForJsonMergePatch(resource, true); - BinaryData resourceInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(resource).toBytes()); + BinaryData resourceInBinaryData = BinaryData.fromObject(resource); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + resourceInBinaryData.getLength(); JsonMergePatchHelper.getResourceAccessor().prepareModelForJsonMergePatch(resource, false); return patchWithMatchHeadersWithResponse(name, resourceInBinaryData, requestOptions).getValue() .toObject(Resource.class); @@ -289,7 +291,9 @@ public Resource patchWithMatchHeaders(String name, Resource resource) { // Generated convenience method for patchWithMatchHeadersWithResponse RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getResourceAccessor().prepareModelForJsonMergePatch(resource, true); - BinaryData resourceInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(resource).toBytes()); + BinaryData resourceInBinaryData = BinaryData.fromObject(resource); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + resourceInBinaryData.getLength(); JsonMergePatchHelper.getResourceAccessor().prepareModelForJsonMergePatch(resource, false); return patchWithMatchHeadersWithResponse(name, resourceInBinaryData, requestOptions).getValue() .toObject(Resource.class); diff --git a/typespec-tests/src/main/java/com/cadl/specialheaders/RepeatabilityHeadersAsyncClient.java b/typespec-tests/src/main/java/com/cadl/specialheaders/RepeatabilityHeadersAsyncClient.java index 24778f5ccc..6d8a73fa22 100644 --- a/typespec-tests/src/main/java/com/cadl/specialheaders/RepeatabilityHeadersAsyncClient.java +++ b/typespec-tests/src/main/java/com/cadl/specialheaders/RepeatabilityHeadersAsyncClient.java @@ -284,7 +284,9 @@ public PollerFlux beginCreateLro(String name, Re // Generated convenience method for beginCreateLroWithModel RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getResourceAccessor().prepareModelForJsonMergePatch(resource, true); - BinaryData resourceInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(resource).toBytes()); + BinaryData resourceInBinaryData = BinaryData.fromObject(resource); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + resourceInBinaryData.getLength(); JsonMergePatchHelper.getResourceAccessor().prepareModelForJsonMergePatch(resource, false); return serviceClient.beginCreateLroWithModelAsync(name, resourceInBinaryData, requestOptions); } diff --git a/typespec-tests/src/main/java/com/cadl/specialheaders/RepeatabilityHeadersClient.java b/typespec-tests/src/main/java/com/cadl/specialheaders/RepeatabilityHeadersClient.java index e1d8eee16a..f1a2280c8b 100644 --- a/typespec-tests/src/main/java/com/cadl/specialheaders/RepeatabilityHeadersClient.java +++ b/typespec-tests/src/main/java/com/cadl/specialheaders/RepeatabilityHeadersClient.java @@ -280,7 +280,9 @@ public SyncPoller beginCreateLro(String name, Re // Generated convenience method for beginCreateLroWithModel RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getResourceAccessor().prepareModelForJsonMergePatch(resource, true); - BinaryData resourceInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(resource).toBytes()); + BinaryData resourceInBinaryData = BinaryData.fromObject(resource); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + resourceInBinaryData.getLength(); JsonMergePatchHelper.getResourceAccessor().prepareModelForJsonMergePatch(resource, false); return serviceClient.beginCreateLroWithModel(name, resourceInBinaryData, requestOptions); } diff --git a/typespec-tests/src/main/java/com/cadl/specialheaders/models/Resource.java b/typespec-tests/src/main/java/com/cadl/specialheaders/models/Resource.java index 1176172de2..2c8cd0cfcb 100644 --- a/typespec-tests/src/main/java/com/cadl/specialheaders/models/Resource.java +++ b/typespec-tests/src/main/java/com/cadl/specialheaders/models/Resource.java @@ -47,6 +47,11 @@ public final class Resource implements JsonSerializable { @Generated private boolean jsonMergePatch; + @Generated + boolean isJsonMergePatch() { + return this.jsonMergePatch; + } + /** * Stores updated model property, the value is property name, not serialized name. */ @@ -54,7 +59,7 @@ public final class Resource implements JsonSerializable { private final Set updatedProperties = new HashSet<>(); @Generated - void serializeAsJsonMergePatch(boolean jsonMergePatch) { + private void serializeAsJsonMergePatch(boolean jsonMergePatch) { this.jsonMergePatch = jsonMergePatch; } @@ -145,7 +150,7 @@ public Resource setType(String type) { @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (jsonMergePatch) { + if (isJsonMergePatch()) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); diff --git a/typespec-tests/src/main/java/com/payload/jsonmergepatch/JsonMergePatchAsyncClient.java b/typespec-tests/src/main/java/com/payload/jsonmergepatch/JsonMergePatchAsyncClient.java index 6472063356..5069483644 100644 --- a/typespec-tests/src/main/java/com/payload/jsonmergepatch/JsonMergePatchAsyncClient.java +++ b/typespec-tests/src/main/java/com/payload/jsonmergepatch/JsonMergePatchAsyncClient.java @@ -268,7 +268,9 @@ public Mono updateResource(ResourcePatch body) { // Generated convenience method for updateResourceWithResponse RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getResourcePatchAccessor().prepareModelForJsonMergePatch(body, true); - BinaryData bodyInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(body).toBytes()); + BinaryData bodyInBinaryData = BinaryData.fromObject(body); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + bodyInBinaryData.getLength(); JsonMergePatchHelper.getResourcePatchAccessor().prepareModelForJsonMergePatch(body, false); return updateResourceWithResponse(bodyInBinaryData, requestOptions).flatMap(FluxUtil::toMono) .map(protocolMethodData -> protocolMethodData.toObject(Resource.class)); @@ -293,7 +295,9 @@ public Mono updateOptionalResource(ResourcePatch body) { RequestOptions requestOptions = new RequestOptions(); if (body != null) { JsonMergePatchHelper.getResourcePatchAccessor().prepareModelForJsonMergePatch(body, true); - BinaryData bodyInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(body).toBytes()); + BinaryData bodyInBinaryData = BinaryData.fromObject(body); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + bodyInBinaryData.getLength(); JsonMergePatchHelper.getResourcePatchAccessor().prepareModelForJsonMergePatch(body, false); requestOptions.setBody(bodyInBinaryData); } diff --git a/typespec-tests/src/main/java/com/payload/jsonmergepatch/JsonMergePatchClient.java b/typespec-tests/src/main/java/com/payload/jsonmergepatch/JsonMergePatchClient.java index 13fdadee8c..4b165a912d 100644 --- a/typespec-tests/src/main/java/com/payload/jsonmergepatch/JsonMergePatchClient.java +++ b/typespec-tests/src/main/java/com/payload/jsonmergepatch/JsonMergePatchClient.java @@ -266,7 +266,9 @@ public Resource updateResource(ResourcePatch body) { // Generated convenience method for updateResourceWithResponse RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getResourcePatchAccessor().prepareModelForJsonMergePatch(body, true); - BinaryData bodyInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(body).toBytes()); + BinaryData bodyInBinaryData = BinaryData.fromObject(body); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + bodyInBinaryData.getLength(); JsonMergePatchHelper.getResourcePatchAccessor().prepareModelForJsonMergePatch(body, false); return updateResourceWithResponse(bodyInBinaryData, requestOptions).getValue().toObject(Resource.class); } @@ -290,7 +292,9 @@ public Resource updateOptionalResource(ResourcePatch body) { RequestOptions requestOptions = new RequestOptions(); if (body != null) { JsonMergePatchHelper.getResourcePatchAccessor().prepareModelForJsonMergePatch(body, true); - BinaryData bodyInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(body).toBytes()); + BinaryData bodyInBinaryData = BinaryData.fromObject(body); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + bodyInBinaryData.getLength(); JsonMergePatchHelper.getResourcePatchAccessor().prepareModelForJsonMergePatch(body, false); requestOptions.setBody(bodyInBinaryData); } diff --git a/typespec-tests/src/main/java/com/payload/jsonmergepatch/implementation/JsonMergePatchHelper.java b/typespec-tests/src/main/java/com/payload/jsonmergepatch/implementation/JsonMergePatchHelper.java index 6b5fbf380d..c198c9ea4f 100644 --- a/typespec-tests/src/main/java/com/payload/jsonmergepatch/implementation/JsonMergePatchHelper.java +++ b/typespec-tests/src/main/java/com/payload/jsonmergepatch/implementation/JsonMergePatchHelper.java @@ -13,16 +13,10 @@ public class JsonMergePatchHelper { private static InnerModelAccessor innerModelAccessor; - private static ResourcePatchAccessor resourcePatchAccessor; - public interface InnerModelAccessor { InnerModel prepareModelForJsonMergePatch(InnerModel innerModel, boolean jsonMergePatchEnabled); } - public interface ResourcePatchAccessor { - ResourcePatch prepareModelForJsonMergePatch(ResourcePatch resourcePatch, boolean jsonMergePatchEnabled); - } - public static void setInnerModelAccessor(InnerModelAccessor accessor) { innerModelAccessor = accessor; } @@ -31,6 +25,12 @@ public static InnerModelAccessor getInnerModelAccessor() { return innerModelAccessor; } + private static ResourcePatchAccessor resourcePatchAccessor; + + public interface ResourcePatchAccessor { + ResourcePatch prepareModelForJsonMergePatch(ResourcePatch resourcePatch, boolean jsonMergePatchEnabled); + } + public static void setResourcePatchAccessor(ResourcePatchAccessor accessor) { resourcePatchAccessor = accessor; } diff --git a/typespec-tests/src/main/java/com/payload/jsonmergepatch/models/InnerModel.java b/typespec-tests/src/main/java/com/payload/jsonmergepatch/models/InnerModel.java index 3bd12a4ae1..bc5a6cb6b8 100644 --- a/typespec-tests/src/main/java/com/payload/jsonmergepatch/models/InnerModel.java +++ b/typespec-tests/src/main/java/com/payload/jsonmergepatch/models/InnerModel.java @@ -35,6 +35,11 @@ public final class InnerModel implements JsonSerializable { @Generated private boolean jsonMergePatch; + @Generated + boolean isJsonMergePatch() { + return this.jsonMergePatch; + } + /** * Stores updated model property, the value is property name, not serialized name. */ @@ -42,7 +47,7 @@ public final class InnerModel implements JsonSerializable { private final Set updatedProperties = new HashSet<>(); @Generated - void serializeAsJsonMergePatch(boolean jsonMergePatch) { + private void serializeAsJsonMergePatch(boolean jsonMergePatch) { this.jsonMergePatch = jsonMergePatch; } @@ -112,7 +117,7 @@ public InnerModel setDescription(String description) { @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (jsonMergePatch) { + if (isJsonMergePatch()) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); diff --git a/typespec-tests/src/main/java/com/payload/jsonmergepatch/models/ResourcePatch.java b/typespec-tests/src/main/java/com/payload/jsonmergepatch/models/ResourcePatch.java index 059cb485cf..fe0c4bb584 100644 --- a/typespec-tests/src/main/java/com/payload/jsonmergepatch/models/ResourcePatch.java +++ b/typespec-tests/src/main/java/com/payload/jsonmergepatch/models/ResourcePatch.java @@ -67,6 +67,11 @@ public final class ResourcePatch implements JsonSerializable { @Generated private boolean jsonMergePatch; + @Generated + boolean isJsonMergePatch() { + return this.jsonMergePatch; + } + /** * Stores updated model property, the value is property name, not serialized name. */ @@ -74,7 +79,7 @@ public final class ResourcePatch implements JsonSerializable { private final Set updatedProperties = new HashSet<>(); @Generated - void serializeAsJsonMergePatch(boolean jsonMergePatch) { + private void serializeAsJsonMergePatch(boolean jsonMergePatch) { this.jsonMergePatch = jsonMergePatch; } @@ -259,7 +264,7 @@ public ResourcePatch setIntArray(List intArray) { @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (jsonMergePatch) { + if (isJsonMergePatch()) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); diff --git a/typespec-tests/src/main/java/com/type/property/nullable/BytesAsyncClient.java b/typespec-tests/src/main/java/com/type/property/nullable/BytesAsyncClient.java index 72c545c0a3..9c03abbe8e 100644 --- a/typespec-tests/src/main/java/com/type/property/nullable/BytesAsyncClient.java +++ b/typespec-tests/src/main/java/com/type/property/nullable/BytesAsyncClient.java @@ -198,7 +198,9 @@ public Mono patchNonNull(BytesProperty body) { // Generated convenience method for patchNonNullWithResponse RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getBytesPropertyAccessor().prepareModelForJsonMergePatch(body, true); - BinaryData bodyInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(body).toBytes()); + BinaryData bodyInBinaryData = BinaryData.fromObject(body); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + bodyInBinaryData.getLength(); JsonMergePatchHelper.getBytesPropertyAccessor().prepareModelForJsonMergePatch(body, false); return patchNonNullWithResponse(bodyInBinaryData, requestOptions).flatMap(FluxUtil::toMono); } @@ -222,7 +224,9 @@ public Mono patchNull(BytesProperty body) { // Generated convenience method for patchNullWithResponse RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getBytesPropertyAccessor().prepareModelForJsonMergePatch(body, true); - BinaryData bodyInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(body).toBytes()); + BinaryData bodyInBinaryData = BinaryData.fromObject(body); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + bodyInBinaryData.getLength(); JsonMergePatchHelper.getBytesPropertyAccessor().prepareModelForJsonMergePatch(body, false); return patchNullWithResponse(bodyInBinaryData, requestOptions).flatMap(FluxUtil::toMono); } diff --git a/typespec-tests/src/main/java/com/type/property/nullable/BytesClient.java b/typespec-tests/src/main/java/com/type/property/nullable/BytesClient.java index d6b925a9ee..f210eb1bbd 100644 --- a/typespec-tests/src/main/java/com/type/property/nullable/BytesClient.java +++ b/typespec-tests/src/main/java/com/type/property/nullable/BytesClient.java @@ -191,7 +191,9 @@ public void patchNonNull(BytesProperty body) { // Generated convenience method for patchNonNullWithResponse RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getBytesPropertyAccessor().prepareModelForJsonMergePatch(body, true); - BinaryData bodyInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(body).toBytes()); + BinaryData bodyInBinaryData = BinaryData.fromObject(body); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + bodyInBinaryData.getLength(); JsonMergePatchHelper.getBytesPropertyAccessor().prepareModelForJsonMergePatch(body, false); patchNonNullWithResponse(bodyInBinaryData, requestOptions).getValue(); } @@ -214,7 +216,9 @@ public void patchNull(BytesProperty body) { // Generated convenience method for patchNullWithResponse RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getBytesPropertyAccessor().prepareModelForJsonMergePatch(body, true); - BinaryData bodyInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(body).toBytes()); + BinaryData bodyInBinaryData = BinaryData.fromObject(body); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + bodyInBinaryData.getLength(); JsonMergePatchHelper.getBytesPropertyAccessor().prepareModelForJsonMergePatch(body, false); patchNullWithResponse(bodyInBinaryData, requestOptions).getValue(); } diff --git a/typespec-tests/src/main/java/com/type/property/nullable/CollectionsByteAsyncClient.java b/typespec-tests/src/main/java/com/type/property/nullable/CollectionsByteAsyncClient.java index 71bfec6b42..982167a662 100644 --- a/typespec-tests/src/main/java/com/type/property/nullable/CollectionsByteAsyncClient.java +++ b/typespec-tests/src/main/java/com/type/property/nullable/CollectionsByteAsyncClient.java @@ -203,7 +203,9 @@ public Mono patchNonNull(CollectionsByteProperty body) { // Generated convenience method for patchNonNullWithResponse RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getCollectionsBytePropertyAccessor().prepareModelForJsonMergePatch(body, true); - BinaryData bodyInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(body).toBytes()); + BinaryData bodyInBinaryData = BinaryData.fromObject(body); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + bodyInBinaryData.getLength(); JsonMergePatchHelper.getCollectionsBytePropertyAccessor().prepareModelForJsonMergePatch(body, false); return patchNonNullWithResponse(bodyInBinaryData, requestOptions).flatMap(FluxUtil::toMono); } @@ -226,7 +228,9 @@ public Mono patchNull(CollectionsByteProperty body) { // Generated convenience method for patchNullWithResponse RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getCollectionsBytePropertyAccessor().prepareModelForJsonMergePatch(body, true); - BinaryData bodyInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(body).toBytes()); + BinaryData bodyInBinaryData = BinaryData.fromObject(body); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + bodyInBinaryData.getLength(); JsonMergePatchHelper.getCollectionsBytePropertyAccessor().prepareModelForJsonMergePatch(body, false); return patchNullWithResponse(bodyInBinaryData, requestOptions).flatMap(FluxUtil::toMono); } diff --git a/typespec-tests/src/main/java/com/type/property/nullable/CollectionsByteClient.java b/typespec-tests/src/main/java/com/type/property/nullable/CollectionsByteClient.java index b0b3ae5ab7..a018f80a74 100644 --- a/typespec-tests/src/main/java/com/type/property/nullable/CollectionsByteClient.java +++ b/typespec-tests/src/main/java/com/type/property/nullable/CollectionsByteClient.java @@ -196,7 +196,9 @@ public void patchNonNull(CollectionsByteProperty body) { // Generated convenience method for patchNonNullWithResponse RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getCollectionsBytePropertyAccessor().prepareModelForJsonMergePatch(body, true); - BinaryData bodyInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(body).toBytes()); + BinaryData bodyInBinaryData = BinaryData.fromObject(body); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + bodyInBinaryData.getLength(); JsonMergePatchHelper.getCollectionsBytePropertyAccessor().prepareModelForJsonMergePatch(body, false); patchNonNullWithResponse(bodyInBinaryData, requestOptions).getValue(); } @@ -218,7 +220,9 @@ public void patchNull(CollectionsByteProperty body) { // Generated convenience method for patchNullWithResponse RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getCollectionsBytePropertyAccessor().prepareModelForJsonMergePatch(body, true); - BinaryData bodyInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(body).toBytes()); + BinaryData bodyInBinaryData = BinaryData.fromObject(body); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + bodyInBinaryData.getLength(); JsonMergePatchHelper.getCollectionsBytePropertyAccessor().prepareModelForJsonMergePatch(body, false); patchNullWithResponse(bodyInBinaryData, requestOptions).getValue(); } diff --git a/typespec-tests/src/main/java/com/type/property/nullable/CollectionsModelAsyncClient.java b/typespec-tests/src/main/java/com/type/property/nullable/CollectionsModelAsyncClient.java index 06c92231b1..d7427edb85 100644 --- a/typespec-tests/src/main/java/com/type/property/nullable/CollectionsModelAsyncClient.java +++ b/typespec-tests/src/main/java/com/type/property/nullable/CollectionsModelAsyncClient.java @@ -211,7 +211,9 @@ public Mono patchNonNull(CollectionsModelProperty body) { // Generated convenience method for patchNonNullWithResponse RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getCollectionsModelPropertyAccessor().prepareModelForJsonMergePatch(body, true); - BinaryData bodyInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(body).toBytes()); + BinaryData bodyInBinaryData = BinaryData.fromObject(body); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + bodyInBinaryData.getLength(); JsonMergePatchHelper.getCollectionsModelPropertyAccessor().prepareModelForJsonMergePatch(body, false); return patchNonNullWithResponse(bodyInBinaryData, requestOptions).flatMap(FluxUtil::toMono); } @@ -234,7 +236,9 @@ public Mono patchNull(CollectionsModelProperty body) { // Generated convenience method for patchNullWithResponse RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getCollectionsModelPropertyAccessor().prepareModelForJsonMergePatch(body, true); - BinaryData bodyInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(body).toBytes()); + BinaryData bodyInBinaryData = BinaryData.fromObject(body); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + bodyInBinaryData.getLength(); JsonMergePatchHelper.getCollectionsModelPropertyAccessor().prepareModelForJsonMergePatch(body, false); return patchNullWithResponse(bodyInBinaryData, requestOptions).flatMap(FluxUtil::toMono); } diff --git a/typespec-tests/src/main/java/com/type/property/nullable/CollectionsModelClient.java b/typespec-tests/src/main/java/com/type/property/nullable/CollectionsModelClient.java index b903129eed..e8d466f2f4 100644 --- a/typespec-tests/src/main/java/com/type/property/nullable/CollectionsModelClient.java +++ b/typespec-tests/src/main/java/com/type/property/nullable/CollectionsModelClient.java @@ -204,7 +204,9 @@ public void patchNonNull(CollectionsModelProperty body) { // Generated convenience method for patchNonNullWithResponse RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getCollectionsModelPropertyAccessor().prepareModelForJsonMergePatch(body, true); - BinaryData bodyInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(body).toBytes()); + BinaryData bodyInBinaryData = BinaryData.fromObject(body); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + bodyInBinaryData.getLength(); JsonMergePatchHelper.getCollectionsModelPropertyAccessor().prepareModelForJsonMergePatch(body, false); patchNonNullWithResponse(bodyInBinaryData, requestOptions).getValue(); } @@ -226,7 +228,9 @@ public void patchNull(CollectionsModelProperty body) { // Generated convenience method for patchNullWithResponse RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getCollectionsModelPropertyAccessor().prepareModelForJsonMergePatch(body, true); - BinaryData bodyInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(body).toBytes()); + BinaryData bodyInBinaryData = BinaryData.fromObject(body); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + bodyInBinaryData.getLength(); JsonMergePatchHelper.getCollectionsModelPropertyAccessor().prepareModelForJsonMergePatch(body, false); patchNullWithResponse(bodyInBinaryData, requestOptions).getValue(); } diff --git a/typespec-tests/src/main/java/com/type/property/nullable/DatetimeOperationAsyncClient.java b/typespec-tests/src/main/java/com/type/property/nullable/DatetimeOperationAsyncClient.java index e2415f9a13..015e1a4a4d 100644 --- a/typespec-tests/src/main/java/com/type/property/nullable/DatetimeOperationAsyncClient.java +++ b/typespec-tests/src/main/java/com/type/property/nullable/DatetimeOperationAsyncClient.java @@ -195,7 +195,9 @@ public Mono patchNonNull(DatetimeProperty body) { // Generated convenience method for patchNonNullWithResponse RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getDatetimePropertyAccessor().prepareModelForJsonMergePatch(body, true); - BinaryData bodyInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(body).toBytes()); + BinaryData bodyInBinaryData = BinaryData.fromObject(body); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + bodyInBinaryData.getLength(); JsonMergePatchHelper.getDatetimePropertyAccessor().prepareModelForJsonMergePatch(body, false); return patchNonNullWithResponse(bodyInBinaryData, requestOptions).flatMap(FluxUtil::toMono); } @@ -218,7 +220,9 @@ public Mono patchNull(DatetimeProperty body) { // Generated convenience method for patchNullWithResponse RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getDatetimePropertyAccessor().prepareModelForJsonMergePatch(body, true); - BinaryData bodyInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(body).toBytes()); + BinaryData bodyInBinaryData = BinaryData.fromObject(body); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + bodyInBinaryData.getLength(); JsonMergePatchHelper.getDatetimePropertyAccessor().prepareModelForJsonMergePatch(body, false); return patchNullWithResponse(bodyInBinaryData, requestOptions).flatMap(FluxUtil::toMono); } diff --git a/typespec-tests/src/main/java/com/type/property/nullable/DatetimeOperationClient.java b/typespec-tests/src/main/java/com/type/property/nullable/DatetimeOperationClient.java index a67f558f06..2b37f0eff2 100644 --- a/typespec-tests/src/main/java/com/type/property/nullable/DatetimeOperationClient.java +++ b/typespec-tests/src/main/java/com/type/property/nullable/DatetimeOperationClient.java @@ -188,7 +188,9 @@ public void patchNonNull(DatetimeProperty body) { // Generated convenience method for patchNonNullWithResponse RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getDatetimePropertyAccessor().prepareModelForJsonMergePatch(body, true); - BinaryData bodyInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(body).toBytes()); + BinaryData bodyInBinaryData = BinaryData.fromObject(body); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + bodyInBinaryData.getLength(); JsonMergePatchHelper.getDatetimePropertyAccessor().prepareModelForJsonMergePatch(body, false); patchNonNullWithResponse(bodyInBinaryData, requestOptions).getValue(); } @@ -210,7 +212,9 @@ public void patchNull(DatetimeProperty body) { // Generated convenience method for patchNullWithResponse RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getDatetimePropertyAccessor().prepareModelForJsonMergePatch(body, true); - BinaryData bodyInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(body).toBytes()); + BinaryData bodyInBinaryData = BinaryData.fromObject(body); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + bodyInBinaryData.getLength(); JsonMergePatchHelper.getDatetimePropertyAccessor().prepareModelForJsonMergePatch(body, false); patchNullWithResponse(bodyInBinaryData, requestOptions).getValue(); } diff --git a/typespec-tests/src/main/java/com/type/property/nullable/DurationOperationAsyncClient.java b/typespec-tests/src/main/java/com/type/property/nullable/DurationOperationAsyncClient.java index c396de9a41..f9c27ea691 100644 --- a/typespec-tests/src/main/java/com/type/property/nullable/DurationOperationAsyncClient.java +++ b/typespec-tests/src/main/java/com/type/property/nullable/DurationOperationAsyncClient.java @@ -195,7 +195,9 @@ public Mono patchNonNull(DurationProperty body) { // Generated convenience method for patchNonNullWithResponse RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getDurationPropertyAccessor().prepareModelForJsonMergePatch(body, true); - BinaryData bodyInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(body).toBytes()); + BinaryData bodyInBinaryData = BinaryData.fromObject(body); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + bodyInBinaryData.getLength(); JsonMergePatchHelper.getDurationPropertyAccessor().prepareModelForJsonMergePatch(body, false); return patchNonNullWithResponse(bodyInBinaryData, requestOptions).flatMap(FluxUtil::toMono); } @@ -218,7 +220,9 @@ public Mono patchNull(DurationProperty body) { // Generated convenience method for patchNullWithResponse RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getDurationPropertyAccessor().prepareModelForJsonMergePatch(body, true); - BinaryData bodyInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(body).toBytes()); + BinaryData bodyInBinaryData = BinaryData.fromObject(body); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + bodyInBinaryData.getLength(); JsonMergePatchHelper.getDurationPropertyAccessor().prepareModelForJsonMergePatch(body, false); return patchNullWithResponse(bodyInBinaryData, requestOptions).flatMap(FluxUtil::toMono); } diff --git a/typespec-tests/src/main/java/com/type/property/nullable/DurationOperationClient.java b/typespec-tests/src/main/java/com/type/property/nullable/DurationOperationClient.java index f9ca5720d3..85ce47003c 100644 --- a/typespec-tests/src/main/java/com/type/property/nullable/DurationOperationClient.java +++ b/typespec-tests/src/main/java/com/type/property/nullable/DurationOperationClient.java @@ -188,7 +188,9 @@ public void patchNonNull(DurationProperty body) { // Generated convenience method for patchNonNullWithResponse RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getDurationPropertyAccessor().prepareModelForJsonMergePatch(body, true); - BinaryData bodyInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(body).toBytes()); + BinaryData bodyInBinaryData = BinaryData.fromObject(body); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + bodyInBinaryData.getLength(); JsonMergePatchHelper.getDurationPropertyAccessor().prepareModelForJsonMergePatch(body, false); patchNonNullWithResponse(bodyInBinaryData, requestOptions).getValue(); } @@ -210,7 +212,9 @@ public void patchNull(DurationProperty body) { // Generated convenience method for patchNullWithResponse RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getDurationPropertyAccessor().prepareModelForJsonMergePatch(body, true); - BinaryData bodyInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(body).toBytes()); + BinaryData bodyInBinaryData = BinaryData.fromObject(body); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + bodyInBinaryData.getLength(); JsonMergePatchHelper.getDurationPropertyAccessor().prepareModelForJsonMergePatch(body, false); patchNullWithResponse(bodyInBinaryData, requestOptions).getValue(); } diff --git a/typespec-tests/src/main/java/com/type/property/nullable/StringOperationAsyncClient.java b/typespec-tests/src/main/java/com/type/property/nullable/StringOperationAsyncClient.java index 171325d915..65759a9ce4 100644 --- a/typespec-tests/src/main/java/com/type/property/nullable/StringOperationAsyncClient.java +++ b/typespec-tests/src/main/java/com/type/property/nullable/StringOperationAsyncClient.java @@ -198,7 +198,9 @@ public Mono patchNonNull(StringProperty body) { // Generated convenience method for patchNonNullWithResponse RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getStringPropertyAccessor().prepareModelForJsonMergePatch(body, true); - BinaryData bodyInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(body).toBytes()); + BinaryData bodyInBinaryData = BinaryData.fromObject(body); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + bodyInBinaryData.getLength(); JsonMergePatchHelper.getStringPropertyAccessor().prepareModelForJsonMergePatch(body, false); return patchNonNullWithResponse(bodyInBinaryData, requestOptions).flatMap(FluxUtil::toMono); } @@ -222,7 +224,9 @@ public Mono patchNull(StringProperty body) { // Generated convenience method for patchNullWithResponse RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getStringPropertyAccessor().prepareModelForJsonMergePatch(body, true); - BinaryData bodyInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(body).toBytes()); + BinaryData bodyInBinaryData = BinaryData.fromObject(body); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + bodyInBinaryData.getLength(); JsonMergePatchHelper.getStringPropertyAccessor().prepareModelForJsonMergePatch(body, false); return patchNullWithResponse(bodyInBinaryData, requestOptions).flatMap(FluxUtil::toMono); } diff --git a/typespec-tests/src/main/java/com/type/property/nullable/StringOperationClient.java b/typespec-tests/src/main/java/com/type/property/nullable/StringOperationClient.java index 0ea24eab72..a1eb0b34e6 100644 --- a/typespec-tests/src/main/java/com/type/property/nullable/StringOperationClient.java +++ b/typespec-tests/src/main/java/com/type/property/nullable/StringOperationClient.java @@ -191,7 +191,9 @@ public void patchNonNull(StringProperty body) { // Generated convenience method for patchNonNullWithResponse RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getStringPropertyAccessor().prepareModelForJsonMergePatch(body, true); - BinaryData bodyInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(body).toBytes()); + BinaryData bodyInBinaryData = BinaryData.fromObject(body); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + bodyInBinaryData.getLength(); JsonMergePatchHelper.getStringPropertyAccessor().prepareModelForJsonMergePatch(body, false); patchNonNullWithResponse(bodyInBinaryData, requestOptions).getValue(); } @@ -214,7 +216,9 @@ public void patchNull(StringProperty body) { // Generated convenience method for patchNullWithResponse RequestOptions requestOptions = new RequestOptions(); JsonMergePatchHelper.getStringPropertyAccessor().prepareModelForJsonMergePatch(body, true); - BinaryData bodyInBinaryData = BinaryData.fromBytes(BinaryData.fromObject(body).toBytes()); + BinaryData bodyInBinaryData = BinaryData.fromObject(body); + // BinaryData.fromObject() will not fire serialization, use getLength() to fire serialization. + bodyInBinaryData.getLength(); JsonMergePatchHelper.getStringPropertyAccessor().prepareModelForJsonMergePatch(body, false); patchNullWithResponse(bodyInBinaryData, requestOptions).getValue(); } diff --git a/typespec-tests/src/main/java/com/type/property/nullable/implementation/JsonMergePatchHelper.java b/typespec-tests/src/main/java/com/type/property/nullable/implementation/JsonMergePatchHelper.java index 018031cd8c..5c89e6280d 100644 --- a/typespec-tests/src/main/java/com/type/property/nullable/implementation/JsonMergePatchHelper.java +++ b/typespec-tests/src/main/java/com/type/property/nullable/implementation/JsonMergePatchHelper.java @@ -18,50 +18,10 @@ public class JsonMergePatchHelper { private static StringPropertyAccessor stringPropertyAccessor; - private static BytesPropertyAccessor bytesPropertyAccessor; - - private static DatetimePropertyAccessor datetimePropertyAccessor; - - private static DurationPropertyAccessor durationPropertyAccessor; - - private static CollectionsBytePropertyAccessor collectionsBytePropertyAccessor; - - private static CollectionsModelPropertyAccessor collectionsModelPropertyAccessor; - - private static InnerModelAccessor innerModelAccessor; - public interface StringPropertyAccessor { StringProperty prepareModelForJsonMergePatch(StringProperty stringProperty, boolean jsonMergePatchEnabled); } - public interface BytesPropertyAccessor { - BytesProperty prepareModelForJsonMergePatch(BytesProperty bytesProperty, boolean jsonMergePatchEnabled); - } - - public interface DatetimePropertyAccessor { - DatetimeProperty prepareModelForJsonMergePatch(DatetimeProperty datetimeProperty, - boolean jsonMergePatchEnabled); - } - - public interface DurationPropertyAccessor { - DurationProperty prepareModelForJsonMergePatch(DurationProperty durationProperty, - boolean jsonMergePatchEnabled); - } - - public interface CollectionsBytePropertyAccessor { - CollectionsByteProperty prepareModelForJsonMergePatch(CollectionsByteProperty collectionsByteProperty, - boolean jsonMergePatchEnabled); - } - - public interface CollectionsModelPropertyAccessor { - CollectionsModelProperty prepareModelForJsonMergePatch(CollectionsModelProperty collectionsModelProperty, - boolean jsonMergePatchEnabled); - } - - public interface InnerModelAccessor { - InnerModel prepareModelForJsonMergePatch(InnerModel innerModel, boolean jsonMergePatchEnabled); - } - public static void setStringPropertyAccessor(StringPropertyAccessor accessor) { stringPropertyAccessor = accessor; } @@ -70,6 +30,12 @@ public static StringPropertyAccessor getStringPropertyAccessor() { return stringPropertyAccessor; } + private static BytesPropertyAccessor bytesPropertyAccessor; + + public interface BytesPropertyAccessor { + BytesProperty prepareModelForJsonMergePatch(BytesProperty bytesProperty, boolean jsonMergePatchEnabled); + } + public static void setBytesPropertyAccessor(BytesPropertyAccessor accessor) { bytesPropertyAccessor = accessor; } @@ -78,6 +44,13 @@ public static BytesPropertyAccessor getBytesPropertyAccessor() { return bytesPropertyAccessor; } + private static DatetimePropertyAccessor datetimePropertyAccessor; + + public interface DatetimePropertyAccessor { + DatetimeProperty prepareModelForJsonMergePatch(DatetimeProperty datetimeProperty, + boolean jsonMergePatchEnabled); + } + public static void setDatetimePropertyAccessor(DatetimePropertyAccessor accessor) { datetimePropertyAccessor = accessor; } @@ -86,6 +59,13 @@ public static DatetimePropertyAccessor getDatetimePropertyAccessor() { return datetimePropertyAccessor; } + private static DurationPropertyAccessor durationPropertyAccessor; + + public interface DurationPropertyAccessor { + DurationProperty prepareModelForJsonMergePatch(DurationProperty durationProperty, + boolean jsonMergePatchEnabled); + } + public static void setDurationPropertyAccessor(DurationPropertyAccessor accessor) { durationPropertyAccessor = accessor; } @@ -94,6 +74,13 @@ public static DurationPropertyAccessor getDurationPropertyAccessor() { return durationPropertyAccessor; } + private static CollectionsBytePropertyAccessor collectionsBytePropertyAccessor; + + public interface CollectionsBytePropertyAccessor { + CollectionsByteProperty prepareModelForJsonMergePatch(CollectionsByteProperty collectionsByteProperty, + boolean jsonMergePatchEnabled); + } + public static void setCollectionsBytePropertyAccessor(CollectionsBytePropertyAccessor accessor) { collectionsBytePropertyAccessor = accessor; } @@ -102,6 +89,13 @@ public static CollectionsBytePropertyAccessor getCollectionsBytePropertyAccessor return collectionsBytePropertyAccessor; } + private static CollectionsModelPropertyAccessor collectionsModelPropertyAccessor; + + public interface CollectionsModelPropertyAccessor { + CollectionsModelProperty prepareModelForJsonMergePatch(CollectionsModelProperty collectionsModelProperty, + boolean jsonMergePatchEnabled); + } + public static void setCollectionsModelPropertyAccessor(CollectionsModelPropertyAccessor accessor) { collectionsModelPropertyAccessor = accessor; } @@ -110,6 +104,12 @@ public static CollectionsModelPropertyAccessor getCollectionsModelPropertyAccess return collectionsModelPropertyAccessor; } + private static InnerModelAccessor innerModelAccessor; + + public interface InnerModelAccessor { + InnerModel prepareModelForJsonMergePatch(InnerModel innerModel, boolean jsonMergePatchEnabled); + } + public static void setInnerModelAccessor(InnerModelAccessor accessor) { innerModelAccessor = accessor; } diff --git a/typespec-tests/src/main/java/com/type/property/nullable/models/BytesProperty.java b/typespec-tests/src/main/java/com/type/property/nullable/models/BytesProperty.java index 538f39a1bd..c22c55ecb0 100644 --- a/typespec-tests/src/main/java/com/type/property/nullable/models/BytesProperty.java +++ b/typespec-tests/src/main/java/com/type/property/nullable/models/BytesProperty.java @@ -36,6 +36,11 @@ public final class BytesProperty implements JsonSerializable { @Generated private boolean jsonMergePatch; + @Generated + boolean isJsonMergePatch() { + return this.jsonMergePatch; + } + /** * Stores updated model property, the value is property name, not serialized name. */ @@ -43,7 +48,7 @@ public final class BytesProperty implements JsonSerializable { private final Set updatedProperties = new HashSet<>(); @Generated - void serializeAsJsonMergePatch(boolean jsonMergePatch) { + private void serializeAsJsonMergePatch(boolean jsonMergePatch) { this.jsonMergePatch = jsonMergePatch; } @@ -115,7 +120,7 @@ public BytesProperty setNullableProperty(byte[] nullableProperty) { @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (jsonMergePatch) { + if (isJsonMergePatch()) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); diff --git a/typespec-tests/src/main/java/com/type/property/nullable/models/CollectionsByteProperty.java b/typespec-tests/src/main/java/com/type/property/nullable/models/CollectionsByteProperty.java index f986d5d5f3..79c6051420 100644 --- a/typespec-tests/src/main/java/com/type/property/nullable/models/CollectionsByteProperty.java +++ b/typespec-tests/src/main/java/com/type/property/nullable/models/CollectionsByteProperty.java @@ -36,6 +36,11 @@ public final class CollectionsByteProperty implements JsonSerializable updatedProperties = new HashSet<>(); @Generated - void serializeAsJsonMergePatch(boolean jsonMergePatch) { + private void serializeAsJsonMergePatch(boolean jsonMergePatch) { this.jsonMergePatch = jsonMergePatch; } @@ -115,7 +120,7 @@ public CollectionsByteProperty setNullableProperty(List nullableProperty @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (jsonMergePatch) { + if (isJsonMergePatch()) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); diff --git a/typespec-tests/src/main/java/com/type/property/nullable/models/CollectionsModelProperty.java b/typespec-tests/src/main/java/com/type/property/nullable/models/CollectionsModelProperty.java index 3621be6222..9cc70ffbea 100644 --- a/typespec-tests/src/main/java/com/type/property/nullable/models/CollectionsModelProperty.java +++ b/typespec-tests/src/main/java/com/type/property/nullable/models/CollectionsModelProperty.java @@ -36,6 +36,11 @@ public final class CollectionsModelProperty implements JsonSerializable updatedProperties = new HashSet<>(); @Generated - void serializeAsJsonMergePatch(boolean jsonMergePatch) { + private void serializeAsJsonMergePatch(boolean jsonMergePatch) { this.jsonMergePatch = jsonMergePatch; } @@ -115,7 +120,7 @@ public CollectionsModelProperty setNullableProperty(List nullablePro @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (jsonMergePatch) { + if (isJsonMergePatch()) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); diff --git a/typespec-tests/src/main/java/com/type/property/nullable/models/DatetimeProperty.java b/typespec-tests/src/main/java/com/type/property/nullable/models/DatetimeProperty.java index 65b21de2d1..d0e5cf6f0a 100644 --- a/typespec-tests/src/main/java/com/type/property/nullable/models/DatetimeProperty.java +++ b/typespec-tests/src/main/java/com/type/property/nullable/models/DatetimeProperty.java @@ -37,6 +37,11 @@ public final class DatetimeProperty implements JsonSerializable updatedProperties = new HashSet<>(); @Generated - void serializeAsJsonMergePatch(boolean jsonMergePatch) { + private void serializeAsJsonMergePatch(boolean jsonMergePatch) { this.jsonMergePatch = jsonMergePatch; } @@ -116,7 +121,7 @@ public DatetimeProperty setNullableProperty(OffsetDateTime nullableProperty) { @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (jsonMergePatch) { + if (isJsonMergePatch()) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); diff --git a/typespec-tests/src/main/java/com/type/property/nullable/models/DurationProperty.java b/typespec-tests/src/main/java/com/type/property/nullable/models/DurationProperty.java index 1270e9c77d..93755f72b8 100644 --- a/typespec-tests/src/main/java/com/type/property/nullable/models/DurationProperty.java +++ b/typespec-tests/src/main/java/com/type/property/nullable/models/DurationProperty.java @@ -37,6 +37,11 @@ public final class DurationProperty implements JsonSerializable updatedProperties = new HashSet<>(); @Generated - void serializeAsJsonMergePatch(boolean jsonMergePatch) { + private void serializeAsJsonMergePatch(boolean jsonMergePatch) { this.jsonMergePatch = jsonMergePatch; } @@ -116,7 +121,7 @@ public DurationProperty setNullableProperty(Duration nullableProperty) { @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (jsonMergePatch) { + if (isJsonMergePatch()) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); diff --git a/typespec-tests/src/main/java/com/type/property/nullable/models/InnerModel.java b/typespec-tests/src/main/java/com/type/property/nullable/models/InnerModel.java index e58ce4b13f..49f6c882d6 100644 --- a/typespec-tests/src/main/java/com/type/property/nullable/models/InnerModel.java +++ b/typespec-tests/src/main/java/com/type/property/nullable/models/InnerModel.java @@ -29,6 +29,11 @@ public final class InnerModel implements JsonSerializable { @Generated private boolean jsonMergePatch; + @Generated + boolean isJsonMergePatch() { + return this.jsonMergePatch; + } + /** * Stores updated model property, the value is property name, not serialized name. */ @@ -36,7 +41,7 @@ public final class InnerModel implements JsonSerializable { private final Set updatedProperties = new HashSet<>(); @Generated - void serializeAsJsonMergePatch(boolean jsonMergePatch) { + private void serializeAsJsonMergePatch(boolean jsonMergePatch) { this.jsonMergePatch = jsonMergePatch; } @@ -84,7 +89,7 @@ public InnerModel setProperty(String property) { @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (jsonMergePatch) { + if (isJsonMergePatch()) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); diff --git a/typespec-tests/src/main/java/com/type/property/nullable/models/StringProperty.java b/typespec-tests/src/main/java/com/type/property/nullable/models/StringProperty.java index c9bd23655f..fc4ec744e7 100644 --- a/typespec-tests/src/main/java/com/type/property/nullable/models/StringProperty.java +++ b/typespec-tests/src/main/java/com/type/property/nullable/models/StringProperty.java @@ -35,6 +35,11 @@ public final class StringProperty implements JsonSerializable { @Generated private boolean jsonMergePatch; + @Generated + boolean isJsonMergePatch() { + return this.jsonMergePatch; + } + /** * Stores updated model property, the value is property name, not serialized name. */ @@ -42,7 +47,7 @@ public final class StringProperty implements JsonSerializable { private final Set updatedProperties = new HashSet<>(); @Generated - void serializeAsJsonMergePatch(boolean jsonMergePatch) { + private void serializeAsJsonMergePatch(boolean jsonMergePatch) { this.jsonMergePatch = jsonMergePatch; } @@ -114,7 +119,7 @@ public StringProperty setNullableProperty(String nullableProperty) { @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (jsonMergePatch) { + if (isJsonMergePatch()) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); From 4a1c36d69476225850606cc1299a850cf9721d9d Mon Sep 17 00:00:00 2001 From: alzimmermsft <48699787+alzimmermsft@users.noreply.github.com> Date: Fri, 17 May 2024 17:37:25 -0400 Subject: [PATCH 3/6] Support json-merge-patch deserialization without setter --- .../autorest/model/javamodel/JavaClass.java | 16 +++ .../autorest/template/ModelTemplate.java | 118 ++++++++++-------- .../StreamSerializationModelTemplate.java | 71 ++++++----- .../models/UserAssignedIdentities.java | 3 +- .../main/java/com/cadl/patch/models/Fish.java | 10 +- .../java/com/cadl/patch/models/Salmon.java | 8 +- .../java/com/cadl/patch/models/Shark.java | 8 +- .../models/MetricAlertCriteria.java | 3 +- 8 files changed, 133 insertions(+), 104 deletions(-) diff --git a/javagen/src/main/java/com/azure/autorest/model/javamodel/JavaClass.java b/javagen/src/main/java/com/azure/autorest/model/javamodel/JavaClass.java index a2c1cf11ea..0299692ff8 100644 --- a/javagen/src/main/java/com/azure/autorest/model/javamodel/JavaClass.java +++ b/javagen/src/main/java/com/azure/autorest/model/javamodel/JavaClass.java @@ -73,6 +73,22 @@ public final void protectedMemberVariable(String variableType, String variableNa addNewLine = true; } + /** + * Adds a variable with the given declaration and visibility. + *

+ * This doesn't support modifiers. If you need to add modifiers, use + * {@link #variable(String, JavaVisibility, JavaModifier...)}. This will just be a non-final, non-static variable + * with the given visibility. + * + * @param variableDeclaration The variable declaration. + * @param visibility The visibility of the variable. + */ + public final void variable(String variableDeclaration, JavaVisibility visibility) { + addExpectedNewLine(); + contents.line(visibility + " " + variableDeclaration + ";"); + addNewLine = true; + } + /** * Adds a variable with the given declaration, visibility, and modifiers. *

diff --git a/javagen/src/main/java/com/azure/autorest/template/ModelTemplate.java b/javagen/src/main/java/com/azure/autorest/template/ModelTemplate.java index c5f09a7970..28e2d42ad8 100644 --- a/javagen/src/main/java/com/azure/autorest/template/ModelTemplate.java +++ b/javagen/src/main/java/com/azure/autorest/template/ModelTemplate.java @@ -43,8 +43,8 @@ import java.util.ArrayList; import java.util.Base64; import java.util.Collections; -import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.List; import java.util.Objects; import java.util.Set; @@ -168,7 +168,7 @@ public final void write(ClientModel model, JavaFile javaFile) { ? JavaVisibility.Private : JavaVisibility.Public; - generateGetterJavadoc(classBlock, model, property); + generateGetterJavadoc(classBlock, property); addGeneratedAnnotation(classBlock); if (property.isAdditionalProperties() && !settings.isStreamStyleSerialization()) { classBlock.annotation("JsonAnyGetter"); @@ -234,15 +234,16 @@ public final void write(ClientModel model, JavaFile javaFile) { addGeneratedAnnotation(classBlock); classBlock.annotation("JsonAnySetter"); MapType mapType = (MapType) property.getClientType(); - classBlock.packagePrivateMethod(String.format("void %s(String key, %s value)", property.getSetterName(), mapType.getValueType()), (methodBlock) -> { + String methodSignature = "void " + property.getSetterName() + "(String key, " + + mapType.getValueType() + " value)"; + classBlock.packagePrivateMethod(methodSignature, methodBlock -> { // The additional properties are null by default, so if this is the first time the value is // being added create the containing map. - // TODO (alzimmer): Should we use LinkedHashMap to retain insertion order? methodBlock.ifBlock(property.getName() + " == null", - ifBlock -> ifBlock.line("%s = new HashMap<>();", property.getName())); + ifBlock -> ifBlock.line(property.getName() + " = new LinkedHashMap<>();")); - methodBlock.line("%s.put(%s, value);", property.getName(), - model.getNeedsFlatten() ? "KEY_ESCAPER.matcher(key).replaceAll(\".\")" : "key"); + String key = model.getNeedsFlatten() ? "KEY_ESCAPER.matcher(key).replaceAll(\".\")" : "key"; + methodBlock.line(property.getName() + ".put(" + key + ", value);"); }); } } @@ -255,19 +256,18 @@ public final void write(ClientModel model, JavaFile javaFile) { classBlock.javadocComment(JavaJavadocComment::inheritDoc); addGeneratedAnnotation(classBlock); classBlock.annotation("Override"); - classBlock.publicMethod(String.format("%s %s(%s %s)", - model.getName(), - parentProperty.getSetterName(), - parentProperty.getClientType(), - parentProperty.getName()), - methodBlock -> { - methodBlock.line(String.format("super.%1$s(%2$s);", parentProperty.getSetterName(), - parentProperty.getName())); - if (ClientModelUtil.isJsonMergePatchModel(model) && settings.isStreamStyleSerialization()) { - methodBlock.line(String.format("this.updatedProperties.add(\"%s\");", parentProperty.getName())); - } - methodBlock.methodReturn("this"); - }); + + String methodSignature = model.getName() + " " + parentProperty.getSetterName() + "(" + + parentProperty.getClientType() + " " + parentProperty.getName() + ")"; + + classBlock.publicMethod(methodSignature, methodBlock -> { + methodBlock.line( + "super." + parentProperty.getSetterName() + "(" + parentProperty.getName() + ");"); + if (ClientModelUtil.isJsonMergePatchModel(model) && settings.isStreamStyleSerialization()) { + methodBlock.line("this.updatedProperties.add(\"" + parentProperty.getName() + "\");"); + } + methodBlock.methodReturn("this"); + }); } } @@ -291,26 +291,26 @@ public final void write(ClientModel model, JavaFile javaFile) { final IType propertyClientTypeFinal = propertyClientType; // getter - generateGetterJavadoc(classBlock, model, property); + generateGetterJavadoc(classBlock, property); addGeneratedAnnotation(classBlock); - classBlock.publicMethod(String.format("%1$s %2$s()", propertyClientType, propertyReference.getGetterName()), methodBlock -> { + classBlock.publicMethod(propertyClientType + " " + propertyReference.getGetterName() + "()", methodBlock -> { // use ternary operator to avoid directly return null - String ifClause = String.format("this.%1$s() == null", targetProperty.getGetterName()); + String ifClause = "this." + targetProperty.getGetterName() + "() == null"; String nullClause = propertyClientTypeFinal.defaultValueExpression(); - String valueClause = String.format("this.%1$s().%2$s()", targetProperty.getGetterName(), property.getGetterName()); + String valueClause = "this." + targetProperty.getGetterName() + "()." + property.getGetterName() + "()"; - methodBlock.methodReturn(String.format("%1$s ? %2$s : %3$s", ifClause, nullClause, valueClause)); + methodBlock.methodReturn(ifClause + " ? " + nullClause + " : " + valueClause); }); // setter if (!propertyIsReadOnly) { generateSetterJavadoc(classBlock, model, property); addGeneratedAnnotation(classBlock); - classBlock.publicMethod(String.format("%1$s %2$s(%3$s %4$s)", model.getName(), propertyReference.getSetterName(), propertyClientType, property.getName()), methodBlock -> { - methodBlock.ifBlock(String.format("this.%1$s() == null", targetProperty.getGetterName()), ifBlock -> - methodBlock.line(String.format("this.%1$s = new %2$s();", targetProperty.getName(), propertyReference.getTargetModelType()))); + classBlock.publicMethod(String.format("%s %s(%s %s)", model.getName(), propertyReference.getSetterName(), propertyClientType, property.getName()), methodBlock -> { + methodBlock.ifBlock(String.format("this.%s() == null", targetProperty.getGetterName()), ifBlock -> + methodBlock.line(String.format("this.%s = new %s();", targetProperty.getName(), propertyReference.getTargetModelType()))); - methodBlock.line(String.format("this.%1$s().%2$s(%3$s);", targetProperty.getGetterName(), property.getSetterName(), property.getName())); + methodBlock.line(String.format("this.%s().%s(%s);", targetProperty.getGetterName(), property.getSetterName(), property.getName())); methodBlock.methodReturn("this"); }); } @@ -350,7 +350,7 @@ private void addImports(Set imports, ClientModel model, JavaSettings set // Also add any potential imports needed to convert the header to the strong type. // If the import isn't used it will be removed later on. imports.add(Base64.class.getName()); - imports.add(HashMap.class.getName()); + imports.add(LinkedHashMap.class.getName()); imports.add(HttpHeader.class.getName()); imports.add(UUID.class.getName()); imports.add(URL.class.getName()); @@ -471,10 +471,10 @@ protected void handlePolymorphism(ClientModel model, boolean hasDerivedModels, J protected void addClassLevelAnnotations(ClientModel model, JavaFile javaFile, JavaSettings settings) { if (model.isUsedInXml()) { if (!CoreUtils.isNullOrEmpty(model.getXmlNamespace())) { - javaFile.annotation(String.format("JacksonXmlRootElement(localName = \"%1$s\", namespace = \"%2$s\")", - model.getXmlName(), model.getXmlNamespace())); + javaFile.annotation("JacksonXmlRootElement(localName = \"" + model.getXmlName() + "\", " + + "namespace = \"" + model.getXmlNamespace() + "\")"); } else { - javaFile.annotation(String.format("JacksonXmlRootElement(localName = \"%1$s\")", model.getXmlName())); + javaFile.annotation("JacksonXmlRootElement(localName = \"" + model.getXmlName() + "\")"); } } @@ -602,7 +602,18 @@ private void addProperties(ClientModel model, JavaClass classBlock, JavaSettings if (ClientModelUtil.includePropertyInConstructor(property, settings)) { classBlock.privateFinalMemberVariable(fieldSignature); } else { - classBlock.privateMemberVariable(fieldSignature); + if (model.isPolymorphicParent() && settings.isStreamStyleSerialization() + && model.getImplementationDetails().getUsages().contains(ImplementationDetails.Usage.JSON_MERGE_PATCH)) { + // Polymorphic parents in stream-style serialization used for json-merge-patch generate a + // package-private field to support setting the value without needing to use a setter. This is done + // as the setter performs a dual action of setting the property and determining whether the property + // is serialized in the patch request. + // This forces generated SDKs to include all models in the polymorphic hierarchy in the same + // package. + classBlock.variable(fieldSignature, JavaVisibility.PackagePrivate); + } else { + classBlock.privateMemberVariable(fieldSignature); + } } } } @@ -956,16 +967,17 @@ private static void addGetterMethod(IType propertyWireType, IType propertyClient if (sourceTypeName.equals(targetTypeName)) { if (treatAsXml && property.isXmlWrapper() && (property.getWireType() instanceof IterableType)) { + String thisGetName = "this." + property.getName(); if (settings.isStreamStyleSerialization()) { - methodBlock.ifBlock("this." + property.getName() + " == null", ifBlock -> - ifBlock.line("this." + property.getName() + " = new ArrayList<>();")); + methodBlock.ifBlock(thisGetName + " == null", ifBlock -> + ifBlock.line(thisGetName + " = new ArrayList<>();")); methodBlock.methodReturn("this." + property.getName()); } else { - methodBlock.ifBlock(String.format("this.%s == null", property.getName()), ifBlock -> + methodBlock.ifBlock(thisGetName + " == null", ifBlock -> ifBlock.line("this.%s = new %s(new ArrayList<%s>());", property.getName(), getPropertyXmlWrapperClassName(property), ((GenericType) property.getWireType()).getTypeArguments()[0])); - methodBlock.methodReturn(String.format("this.%s.items", property.getName())); + methodBlock.methodReturn(thisGetName + ".items"); } } else { methodBlock.methodReturn(expression); @@ -1023,7 +1035,7 @@ private static void addSetterMethod(IType propertyWireType, IType propertyClient } if (isJsonMergePatchModel) { - methodBlock.line(String.format("this.updatedProperties.add(\"%s\");", property.getName())); + methodBlock.line("this.updatedProperties.add(\"" + property.getName() + "\");"); } methodBlock.methodReturn("this"); @@ -1053,21 +1065,18 @@ private void addPropertyValidations(JavaClass classBlock, ClientModel model, Jav JavaIfBlock nullCheck = methodBlock.ifBlock(String.format("%s() == null", getGetterName(model, property)), ifBlock -> { final String errorMessage = String.format("\"Missing required property %s in model %s\"", property.getName(), model.getName()); if (settings.isUseClientLogger()) { - ifBlock.line(String.format( - "throw LOGGER.atError().log(new IllegalArgumentException(%s));", - errorMessage)); + ifBlock.line( + "throw LOGGER.atError().log(new IllegalArgumentException(" + errorMessage + "));"); } else { - ifBlock.line(String.format( - "throw new IllegalArgumentException(%s);", - errorMessage)); + ifBlock.line("throw new IllegalArgumentException(" + errorMessage + ");"); } }); if (validation != null) { nullCheck.elseBlock(elseBlock -> elseBlock.line(validation + ";")); } } else if (validation != null) { - methodBlock.ifBlock(String.format("%s() != null", getGetterName(model, property)), ifBlock -> - ifBlock.line(validation + ";")); + methodBlock.ifBlock(getGetterName(model, property) + "() != null", + ifBlock -> ifBlock.line(validation + ";")); } } }); @@ -1215,11 +1224,10 @@ protected void addGeneratedAnnotation(JavaContext classBlock) { } // Javadoc for getter method - private static void generateGetterJavadoc(JavaClass classBlock, ClientModel model, - ClientModelPropertyAccess property) { + private static void generateGetterJavadoc(JavaClass classBlock, ClientModelPropertyAccess property) { classBlock.javadocComment(comment -> { - comment.description(String.format("Get the %1$s property: %2$s", property.getName(), property.getDescription())); - comment.methodReturns(String.format("the %1$s value", property.getName())); + comment.description("Get the " + property.getName() + " property: " + property.getDescription()); + comment.methodReturns("the " + property.getName() + " value"); }); } @@ -1228,15 +1236,15 @@ private static void generateSetterJavadoc(JavaClass classBlock, ClientModel mode ClientModelPropertyAccess property) { classBlock.javadocComment((comment) -> { if (property.getDescription() == null || property.getDescription().contains(MISSING_SCHEMA)) { - comment.description(String.format("Set the %s property", property.getName())); + comment.description("Set the " + property.getName() + " property"); } else { - comment.description(String.format("Set the %s property: %s", property.getName(), property.getDescription())); + comment.description("Set the " + property.getName() + " property: " + property.getDescription()); } if (property.isRequiredForCreate() && !property.isRequired()) { comment.line("

Required when create the resource.

"); } - comment.param(property.getName(), String.format("the %s value to set", property.getName())); - comment.methodReturns(String.format("the %s object itself.", model.getName())); + comment.param(property.getName(), "the " + property.getName() + " value to set"); + comment.methodReturns("the " + model.getName() + " object itself."); }); } diff --git a/javagen/src/main/java/com/azure/autorest/template/StreamSerializationModelTemplate.java b/javagen/src/main/java/com/azure/autorest/template/StreamSerializationModelTemplate.java index a8680f9d50..9c89d061a4 100644 --- a/javagen/src/main/java/com/azure/autorest/template/StreamSerializationModelTemplate.java +++ b/javagen/src/main/java/com/azure/autorest/template/StreamSerializationModelTemplate.java @@ -746,6 +746,8 @@ private static void writeTerminalTypeFromJson(JavaClass classBlock, ClientModelP private static void writeFromJsonDeserialization(JavaBlock methodBlock, ClientModelPropertiesManager propertiesManager, JavaSettings settings) { + boolean polymorphicJsonMergePatchScenario = propertiesManager.getModel().isPolymorphic() + && ClientModelUtil.isJsonMergePatchModel(propertiesManager.getModel()); // Add the deserialization logic. methodBlock.indent(() -> { // Initialize local variables to track what has been deserialized. @@ -760,7 +762,7 @@ private static void writeFromJsonDeserialization(JavaBlock methodBlock, BiConsumer consumer = (property, fromSuper) -> handleJsonPropertyDeserialization(property, propertiesManager.getDeserializedModelName(), whileBlock, ifBlockReference, fieldNameVariableName, fromSuper, - propertiesManager.hasConstructorArguments(), settings); + propertiesManager.hasConstructorArguments(), settings, polymorphicJsonMergePatchScenario); // Constants are skipped as they aren't deserialized. propertiesManager.forEachSuperRequiredProperty(property -> { @@ -784,7 +786,7 @@ private static void writeFromJsonDeserialization(JavaBlock methodBlock, handleFlattenedPropertiesDeserialization(propertiesManager.getJsonFlattenedPropertiesTree(), methodBlock, ifBlock, propertiesManager.getAdditionalProperties(), propertiesManager.getJsonReaderFieldNameVariableName(), propertiesManager.hasConstructorArguments(), - settings); + settings, polymorphicJsonMergePatchScenario); // All properties have been checked for, add an else block that will either ignore unknown properties // or add them into an additional properties bag. @@ -795,7 +797,7 @@ private static void writeFromJsonDeserialization(JavaBlock methodBlock, }); // Add the validation and return logic. - handleReadReturn(methodBlock, propertiesManager.getModel().getName(), propertiesManager, false, settings); + handleReadReturn(methodBlock, propertiesManager.getModel().getName(), propertiesManager, settings); } /** @@ -960,7 +962,8 @@ private static void addReaderWhileLoop(JavaBlock methodBlock, boolean initialize private static void handleJsonPropertyDeserialization(ClientModelProperty property, String modelVariableName, JavaBlock methodBlock, AtomicReference ifBlockReference, String fieldNameVariableName, - boolean fromSuper, boolean hasConstructorArguments, JavaSettings settings) { + boolean fromSuper, boolean hasConstructorArguments, JavaSettings settings, + boolean polymorphicJsonMergePatchScenario) { // Property will be handled later by flattened deserialization. if (property.getNeedsFlatten()) { return; @@ -968,14 +971,14 @@ private static void handleJsonPropertyDeserialization(ClientModelProperty proper JavaIfBlock ifBlock = ifBlockReference.get(); ifBlock = handleJsonPropertyDeserialization(property, modelVariableName, methodBlock, ifBlock, - fieldNameVariableName, fromSuper, hasConstructorArguments, settings); + fieldNameVariableName, fromSuper, hasConstructorArguments, settings, polymorphicJsonMergePatchScenario); ifBlockReference.set(ifBlock); } private static JavaIfBlock handleJsonPropertyDeserialization(ClientModelProperty property, String modelVariableName, JavaBlock methodBlock, JavaIfBlock ifBlock, String fieldNameVariableName, boolean fromSuper, - boolean hasConstructorArguments, JavaSettings settings) { + boolean hasConstructorArguments, JavaSettings settings, boolean polymorphicJsonMergePatchScenario) { String jsonPropertyName = property.getSerializedName(); if (CoreUtils.isNullOrEmpty(jsonPropertyName)) { return ifBlock; @@ -983,24 +986,24 @@ private static JavaIfBlock handleJsonPropertyDeserialization(ClientModelProperty return ifOrElseIf(methodBlock, ifBlock, "\"" + jsonPropertyName + "\".equals(" + fieldNameVariableName + ")", deserializationBlock -> generateJsonDeserializationLogic(deserializationBlock, modelVariableName, property, - fromSuper, hasConstructorArguments, settings)); + fromSuper, hasConstructorArguments, settings, polymorphicJsonMergePatchScenario)); } private static void handleFlattenedPropertiesDeserialization( JsonFlattenedPropertiesTree flattenedProperties, JavaBlock methodBlock, JavaIfBlock ifBlock, ClientModelProperty additionalProperties, String fieldNameVariableName, boolean hasConstructorArguments, - JavaSettings settings) { + JavaSettings settings, boolean polymorphicJsonMergePatchScenario) { // The initial call to handle flattened properties is using the base node which is just a holder. for (JsonFlattenedPropertiesTree structure : flattenedProperties.getChildrenNodes().values()) { handleFlattenedPropertiesDeserializationHelper(structure, methodBlock, ifBlock, additionalProperties, - fieldNameVariableName, hasConstructorArguments, settings); + fieldNameVariableName, hasConstructorArguments, settings, polymorphicJsonMergePatchScenario); } } private static JavaIfBlock handleFlattenedPropertiesDeserializationHelper( JsonFlattenedPropertiesTree flattenedProperties, JavaBlock methodBlock, JavaIfBlock ifBlock, ClientModelProperty additionalProperties, String fieldNameVariableName, boolean hasConstructorArguments, - JavaSettings settings) { + JavaSettings settings, boolean polymorphicJsonMergePatchScenario) { ClientModelPropertyWithMetadata propertyWithMetadata = flattenedProperties.getProperty(); if (propertyWithMetadata != null) { String modelVariableName = "deserialized" + propertyWithMetadata.getModel().getName(); @@ -1010,7 +1013,7 @@ private static JavaIfBlock handleFlattenedPropertiesDeserializationHelper( "\"" + flattenedProperties.getNodeName() + "\".equals(" + fieldNameVariableName + ")", deserializationBlock -> generateJsonDeserializationLogic(deserializationBlock, modelVariableName, propertyWithMetadata.getProperty(), propertyWithMetadata.isFromSuperClass(), -hasConstructorArguments, settings)); + hasConstructorArguments, settings, polymorphicJsonMergePatchScenario)); } else { // Otherwise this is an intermediate location and a while loop reader needs to be added. return ifOrElseIf(methodBlock, ifBlock, @@ -1020,7 +1023,7 @@ private static JavaIfBlock handleFlattenedPropertiesDeserializationHelper( for (JsonFlattenedPropertiesTree structure : flattenedProperties.getChildrenNodes().values()) { innerIfBlock = handleFlattenedPropertiesDeserializationHelper(structure, methodBlock, innerIfBlock, additionalProperties, fieldNameVariableName, hasConstructorArguments, - settings); + settings, polymorphicJsonMergePatchScenario); } handleUnknownJsonFieldDeserialization(whileBlock, innerIfBlock, additionalProperties, @@ -1030,7 +1033,8 @@ private static JavaIfBlock handleFlattenedPropertiesDeserializationHelper( } private static void generateJsonDeserializationLogic(JavaBlock deserializationBlock, String modelVariableName, - ClientModelProperty property, boolean fromSuper, boolean hasConstructorArguments, JavaSettings settings) { + ClientModelProperty property, boolean fromSuper, boolean hasConstructorArguments, JavaSettings settings, + boolean polymorphicJsonMergePatchScenario) { IType wireType = property.getWireType(); IType clientType = property.getClientType(); @@ -1044,7 +1048,8 @@ private static void generateJsonDeserializationLogic(JavaBlock deserializationBl && (includePropertyInConstructor(property, settings) || (fromSuper && !property.isReadOnly())); BiConsumer simpleDeserializationConsumer = (logic, block) -> { if (!hasConstructorArguments) { - handleSettingDeserializedValue(block, modelVariableName, property, logic, fromSuper); + handleSettingDeserializedValue(block, modelVariableName, property, logic, fromSuper, + polymorphicJsonMergePatchScenario); } else { block.line(property.getName() + " = " + logic + ";"); } @@ -1075,7 +1080,7 @@ private static void generateJsonDeserializationLogic(JavaBlock deserializationBl } else if (wireType == ClassType.OBJECT) { if (!hasConstructorArguments) { handleSettingDeserializedValue(deserializationBlock, modelVariableName, property, - "reader.readUntyped()", fromSuper); + "reader.readUntyped()", fromSuper, polymorphicJsonMergePatchScenario); } else { deserializationBlock.line(property.getName() + " = reader.readUntyped();"); } @@ -1090,7 +1095,7 @@ private static void generateJsonDeserializationLogic(JavaBlock deserializationBl if (!hasConstructorArguments) { handleSettingDeserializedValue(deserializationBlock, modelVariableName, property, property.getName(), - fromSuper); + fromSuper, polymorphicJsonMergePatchScenario); } } else if (wireType instanceof MapType) { if (!hasConstructorArguments) { @@ -1105,7 +1110,7 @@ private static void generateJsonDeserializationLogic(JavaBlock deserializationBl if (!hasConstructorArguments) { handleSettingDeserializedValue(deserializationBlock, modelVariableName, property, property.getName(), - fromSuper); + fromSuper, polymorphicJsonMergePatchScenario); } } else { // TODO (alzimmer): Resolve this as deserialization logic generation needs to handle all cases. @@ -1256,7 +1261,7 @@ private static void handleUnknownJsonFieldDeserialization(JavaBlock methodBlock, * @param propertiesManager The property manager for the model. */ private static void handleReadReturn(JavaBlock methodBlock, String modelName, - ClientModelPropertiesManager propertiesManager, boolean isXml, JavaSettings settings) { + ClientModelPropertiesManager propertiesManager, JavaSettings settings) { StringBuilder constructorArgs = new StringBuilder(); propertiesManager.forEachSuperConstructorProperty(arg -> addConstructorParameter(constructorArgs, arg.getName())); @@ -1270,7 +1275,7 @@ private static void handleReadReturn(JavaBlock methodBlock, String modelName, if (ifStatementBuilder.length() > 0) { methodBlock.ifBlock(ifStatementBuilder.toString(), ifAction -> - createObjectAndReturn(methodBlock, modelName, constructorArgs.toString(), propertiesManager, isXml)); + createObjectAndReturn(methodBlock, modelName, constructorArgs.toString(), propertiesManager)); if (propertiesManager.getRequiredPropertiesCount() == 1) { StringBuilder stringBuilder = new StringBuilder(); @@ -1286,15 +1291,17 @@ private static void handleReadReturn(JavaBlock methodBlock, String modelName, methodBlock.line("throw new IllegalStateException(\"Missing required property/properties: \" + String.join(\", \", missingProperties));"); } } else { - createObjectAndReturn(methodBlock, modelName, constructorArgs.toString(), propertiesManager, isXml); + createObjectAndReturn(methodBlock, modelName, constructorArgs.toString(), propertiesManager); } } else { - createObjectAndReturn(methodBlock, modelName, constructorArgs.toString(), propertiesManager, isXml); + createObjectAndReturn(methodBlock, modelName, constructorArgs.toString(), propertiesManager); } } private static void createObjectAndReturn(JavaBlock methodBlock, String modelName, String constructorArgs, - ClientModelPropertiesManager propertiesManager, boolean isXml) { + ClientModelPropertiesManager propertiesManager) { + boolean polymorphicJsonMergePatchScenario = propertiesManager.getModel().isPolymorphic() + && ClientModelUtil.isJsonMergePatchModel(propertiesManager.getModel()); if (propertiesManager.hasConstructorArguments()) { if (propertiesManager.getSetterPropertiesCount() == 0 && propertiesManager.getReadOnlyPropertiesCount() == 0 @@ -1309,7 +1316,7 @@ private static void createObjectAndReturn(JavaBlock methodBlock, String modelNam BiConsumer handleSettingDeserializedValue = (property, fromSuper) -> handleSettingDeserializedValue(methodBlock, propertiesManager.getDeserializedModelName(), property, - property.getName(), fromSuper); + property.getName(), fromSuper, polymorphicJsonMergePatchScenario); propertiesManager.forEachSuperReadOnlyProperty(property -> handleSettingDeserializedValue.accept(property, true)); propertiesManager.forEachSuperSetterProperty(property -> handleSettingDeserializedValue.accept(property, true)); @@ -1320,11 +1327,11 @@ private static void createObjectAndReturn(JavaBlock methodBlock, String modelNam if (propertiesManager.getAdditionalProperties() != null) { handleSettingDeserializedValue(methodBlock, propertiesManager.getDeserializedModelName(), propertiesManager.getAdditionalProperties(), propertiesManager.getAdditionalProperties().getName(), - false); + false, polymorphicJsonMergePatchScenario); } else if (propertiesManager.getSuperAdditionalPropertiesProperty() != null) { handleSettingDeserializedValue(methodBlock, propertiesManager.getDeserializedModelName(), propertiesManager.getSuperAdditionalPropertiesProperty(), propertiesManager.getSuperAdditionalPropertiesProperty().getName(), - true); + true, polymorphicJsonMergePatchScenario); } methodBlock.line(); @@ -1384,10 +1391,10 @@ private static void addFoundValidationIfCheck(JavaBlock methodBlock, ClientModel } private static void handleSettingDeserializedValue(JavaBlock methodBlock, String modelVariableName, - ClientModelProperty property, String value, boolean fromSuper) { + ClientModelProperty property, String value, boolean fromSuper, boolean polymorphicJsonMergePatchScenario) { // If the property is defined in a super class use the setter as this will be able to set the value in the // super class. - if (fromSuper) { + if (fromSuper && !polymorphicJsonMergePatchScenario) { methodBlock.line(modelVariableName + "." + property.getSetterName() + "(" + value + ");"); } else { methodBlock.line(modelVariableName + "." + property.getName() + " = " + value + ";"); @@ -1817,7 +1824,7 @@ private static void writeFromXmlDeserialization(JavaBlock methodBlock, }); // Add the validation and return logic. - handleReadReturn(methodBlock, propertiesManager.getModel().getName(), propertiesManager, true, settings); + handleReadReturn(methodBlock, propertiesManager.getModel().getName(), propertiesManager, settings); } private static void deserializeXmlAttribute(JavaBlock methodBlock, ClientModelProperty attribute, @@ -1844,7 +1851,7 @@ private static void deserializeXmlAttribute(JavaBlock methodBlock, ClientModelPr methodBlock.line("%s %s = %s;", attribute.getClientType(), attribute.getName(), xmlAttributeDeserialization); } else { handleSettingDeserializedValue(methodBlock, propertiesManager.getDeserializedModelName(), attribute, - xmlAttributeDeserialization, fromSuper); + xmlAttributeDeserialization, fromSuper, false); } } @@ -1852,10 +1859,10 @@ private static void deserializeXmlText(JavaBlock methodBlock, ClientModelPropert ClientModelPropertiesManager propertiesManager, boolean fromSuper) { String xmlTextDeserialization = getSimpleXmlDeserialization(text.getWireType(), "reader", null, null, null, false); if (propertiesManager.hasConstructorArguments()) { - methodBlock.line("%s %s = %s;", text.getClientType(), text.getName(), xmlTextDeserialization); + methodBlock.line(text.getClientType() + " " + text.getName() + " = " + xmlTextDeserialization + ";"); } else { handleSettingDeserializedValue(methodBlock, propertiesManager.getDeserializedModelName(), text, - xmlTextDeserialization, fromSuper); + xmlTextDeserialization, fromSuper, false); } } @@ -1904,7 +1911,7 @@ private static void generateXmlDeserializationLogic(JavaBlock deserializationBlo deserializationBlock.line(property.getName() + " = " + simpleDeserialization + ";"); } else { handleSettingDeserializedValue(deserializationBlock, propertiesManager.getDeserializedModelName(), - property, simpleDeserialization, fromSuper); + property, simpleDeserialization, fromSuper, false); } } else if (wireType instanceof IterableType) { IType elementType = ((IterableType) wireType).getElementType(); diff --git a/typespec-tests/src/main/java/com/cadl/armresourceprovider/models/UserAssignedIdentities.java b/typespec-tests/src/main/java/com/cadl/armresourceprovider/models/UserAssignedIdentities.java index 21dcbab571..8b54f8733e 100644 --- a/typespec-tests/src/main/java/com/cadl/armresourceprovider/models/UserAssignedIdentities.java +++ b/typespec-tests/src/main/java/com/cadl/armresourceprovider/models/UserAssignedIdentities.java @@ -8,7 +8,6 @@ import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonIgnore; -import java.util.HashMap; import java.util.Map; /** @@ -70,7 +69,7 @@ public UserAssignedIdentities withAdditionalProperties(Map(); + additionalProperties = new LinkedHashMap<>(); } additionalProperties.put(key, value); } diff --git a/typespec-tests/src/main/java/com/cadl/patch/models/Fish.java b/typespec-tests/src/main/java/com/cadl/patch/models/Fish.java index 110a9cf6ef..de5467ae1b 100644 --- a/typespec-tests/src/main/java/com/cadl/patch/models/Fish.java +++ b/typespec-tests/src/main/java/com/cadl/patch/models/Fish.java @@ -24,31 +24,31 @@ public class Fish implements JsonSerializable { * The kind property. */ @Generated - private String kind; + String kind; /* * The id property. */ @Generated - private String id; + String id; /* * The name property. */ @Generated - private String name; + String name; /* * The age property. */ @Generated - private int age; + int age; /* * The color property. */ @Generated - private String color; + String color; @Generated private boolean jsonMergePatch; diff --git a/typespec-tests/src/main/java/com/cadl/patch/models/Salmon.java b/typespec-tests/src/main/java/com/cadl/patch/models/Salmon.java index 6d4d2598b0..1e0e982670 100644 --- a/typespec-tests/src/main/java/com/cadl/patch/models/Salmon.java +++ b/typespec-tests/src/main/java/com/cadl/patch/models/Salmon.java @@ -279,10 +279,10 @@ public static Salmon fromJson(JsonReader jsonReader) throws IOException { } } Salmon deserializedSalmon = new Salmon(); - deserializedSalmon.setId(id); - deserializedSalmon.setName(name); - deserializedSalmon.setAge(age); - deserializedSalmon.setColor(color); + deserializedSalmon.id = id; + deserializedSalmon.name = name; + deserializedSalmon.age = age; + deserializedSalmon.color = color; deserializedSalmon.kind = kind; deserializedSalmon.friends = friends; deserializedSalmon.hate = hate; diff --git a/typespec-tests/src/main/java/com/cadl/patch/models/Shark.java b/typespec-tests/src/main/java/com/cadl/patch/models/Shark.java index cb2b8d4d87..47d02d58a6 100644 --- a/typespec-tests/src/main/java/com/cadl/patch/models/Shark.java +++ b/typespec-tests/src/main/java/com/cadl/patch/models/Shark.java @@ -145,10 +145,10 @@ public static Shark fromJson(JsonReader jsonReader) throws IOException { } } Shark deserializedShark = new Shark(); - deserializedShark.setId(id); - deserializedShark.setName(name); - deserializedShark.setAge(age); - deserializedShark.setColor(color); + deserializedShark.id = id; + deserializedShark.name = name; + deserializedShark.age = age; + deserializedShark.color = color; deserializedShark.kind = kind; return deserializedShark; diff --git a/vanilla-tests/src/main/java/fixtures/inheritance/passdiscriminator/models/MetricAlertCriteria.java b/vanilla-tests/src/main/java/fixtures/inheritance/passdiscriminator/models/MetricAlertCriteria.java index cd9d78c1ed..e413559f66 100644 --- a/vanilla-tests/src/main/java/fixtures/inheritance/passdiscriminator/models/MetricAlertCriteria.java +++ b/vanilla-tests/src/main/java/fixtures/inheritance/passdiscriminator/models/MetricAlertCriteria.java @@ -13,7 +13,6 @@ import com.fasterxml.jackson.annotation.JsonTypeId; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeName; -import java.util.HashMap; import java.util.Map; /** @@ -84,7 +83,7 @@ public MetricAlertCriteria setAdditionalProperties(Map additiona @JsonAnySetter void setAdditionalProperties(String key, Object value) { if (additionalProperties == null) { - additionalProperties = new HashMap<>(); + additionalProperties = new LinkedHashMap<>(); } additionalProperties.put(key, value); } From 76c104d5d09cb8ae533c5f0e76a2fbe85f8dc026 Mon Sep 17 00:00:00 2001 From: alzimmermsft <48699787+alzimmermsft@users.noreply.github.com> Date: Tue, 21 May 2024 13:30:50 -0400 Subject: [PATCH 4/6] Use access helper pattern instead of package-private fields and methods --- .../ClientModelPropertiesManager.java | 10 +- .../model/clientmodel/ClientModel.java | 12 ++ .../clientmodel/ClientModelProperty.java | 4 +- .../ClientModelPropertyReference.java | 23 ++- .../JsonMergePatchHelperTemplate.java | 57 +++++-- .../autorest/template/ModelTemplate.java | 85 ++++++---- .../StreamSerializationModelTemplate.java | 146 ++++++++++------- .../azure/autorest/util/ClientModelUtil.java | 2 +- .../implementation/JsonMergePatchHelper.java | 4 + .../azure/core/basic/models/FirstItem.java | 6 +- .../azure/core/basic/models/SecondItem.java | 6 +- .../_specs_/azure/core/basic/models/User.java | 46 +++--- .../azure/core/basic/models/UserOrder.java | 41 +++-- .../azure/core/traits/models/User.java | 10 +- .../models/UserAssignedIdentities.java | 1 + .../implementation/JsonMergePatchHelper.java | 4 + .../cadl/flatten/models/TodoItemPatch.java | 27 ++-- .../flatten/models/UpdatePatchRequest.java | 28 ++-- .../com/cadl/literalservice/models/Model.java | 6 +- .../cadl/longrunning/models/JobResult.java | 30 +--- .../multicontenttypes/models/Resource.java | 10 +- .../implementation/JsonMergePatchHelper.java | 14 ++ .../main/java/com/cadl/patch/models/Fish.java | 83 ++++++---- .../com/cadl/patch/models/InnerModel.java | 27 ++-- .../java/com/cadl/patch/models/Resource.java | 71 ++++----- .../java/com/cadl/patch/models/Salmon.java | 38 ++--- .../java/com/cadl/patch/models/SawShark.java | 148 ++++++++++++++++++ .../java/com/cadl/patch/models/Shark.java | 81 ++++++---- .../implementation/JsonMergePatchHelper.java | 2 + .../cadl/specialheaders/models/Resource.java | 45 +++--- .../implementation/JsonMergePatchHelper.java | 4 + .../jsonmergepatch/models/InnerModel.java | 27 ++-- .../jsonmergepatch/models/ResourcePatch.java | 27 ++-- .../implementation/JsonMergePatchHelper.java | 14 ++ .../nullable/models/BytesProperty.java | 27 ++-- .../models/CollectionsByteProperty.java | 31 ++-- .../models/CollectionsModelProperty.java | 31 ++-- .../nullable/models/DatetimeProperty.java | 28 ++-- .../nullable/models/DurationProperty.java | 28 ++-- .../property/nullable/models/InnerModel.java | 27 ++-- .../nullable/models/StringProperty.java | 27 ++-- .../models/BooleanLiteralProperty.java | 4 +- .../models/FloatLiteralProperty.java | 4 +- .../valuetypes/models/IntLiteralProperty.java | 4 +- .../models/StringLiteralProperty.java | 4 +- .../models/UnionEnumValueProperty.java | 4 +- typespec-tests/tsp/patch.tsp | 7 + .../models/MetricAlertCriteria.java | 1 + 48 files changed, 843 insertions(+), 523 deletions(-) create mode 100644 typespec-tests/src/main/java/com/cadl/patch/models/SawShark.java diff --git a/javagen/src/main/java/com/azure/autorest/implementation/ClientModelPropertiesManager.java b/javagen/src/main/java/com/azure/autorest/implementation/ClientModelPropertiesManager.java index e93d32efd9..4e2415f48e 100644 --- a/javagen/src/main/java/com/azure/autorest/implementation/ClientModelPropertiesManager.java +++ b/javagen/src/main/java/com/azure/autorest/implementation/ClientModelPropertiesManager.java @@ -95,6 +95,7 @@ public ClientModelPropertiesManager(ClientModel model, JavaSettings settings) { Map flattenedProperties = new LinkedHashMap<>(); boolean hasRequiredProperties = false; + boolean hasConstructorArguments = false; superConstructorProperties = new LinkedHashMap<>(); superRequiredProperties = new LinkedHashMap<>(); superSetterProperties = new LinkedHashMap<>(); @@ -140,6 +141,7 @@ public ClientModelPropertiesManager(ClientModel model, JavaSettings settings) { superPropertyConsumer(property, superRequiredProperties, superConstructorProperties, superReadOnlyProperties, superSetterProperties, settings); hasRequiredProperties |= property.isRequired(); + hasConstructorArguments |= ClientModelUtil.includePropertyInConstructor(property, settings); } if (property.getNeedsFlatten()) { @@ -181,6 +183,7 @@ public ClientModelPropertiesManager(ClientModel model, JavaSettings settings) { if (!property.isConstant()) { if (ClientModelUtil.includePropertyInConstructor(property, settings)) { constructorProperties.put(property.getSerializedName(), property); + hasConstructorArguments = true; } else { readOnlyProperties.put(property.getSerializedName(), property); } @@ -227,16 +230,11 @@ public ClientModelPropertiesManager(ClientModel model, JavaSettings settings) { } } - boolean requiredConstructorProperties = hasRequiredProperties && settings.isRequiredFieldsAsConstructorArgs(); - boolean readOnlyConstructorProperties = settings.isRequiredFieldsAsConstructorArgs() - && settings.isIncludeReadOnlyInConstructorArgs() - && (!CoreUtils.isNullOrEmpty(readOnlyProperties) || !CoreUtils.isNullOrEmpty(superReadOnlyProperties)); - this.hasRequiredProperties = hasRequiredProperties; this.requiredPropertiesCount = requiredProperties.size() + superRequiredProperties.size(); this.setterPropertiesCount = setterProperties.size() + superSetterProperties.size(); this.readOnlyPropertiesCount = readOnlyProperties.size() + superReadOnlyProperties.size(); - this.hasConstructorArguments = requiredConstructorProperties || readOnlyConstructorProperties; + this.hasConstructorArguments = hasConstructorArguments; this.hasXmlElements = hasXmlElements; this.hasXmlTexts = hasXmlTexts; this.discriminatorProperty = discriminatorProperty; diff --git a/javagen/src/main/java/com/azure/autorest/model/clientmodel/ClientModel.java b/javagen/src/main/java/com/azure/autorest/model/clientmodel/ClientModel.java index b9c240b5de..da88ba1c15 100644 --- a/javagen/src/main/java/com/azure/autorest/model/clientmodel/ClientModel.java +++ b/javagen/src/main/java/com/azure/autorest/model/clientmodel/ClientModel.java @@ -19,52 +19,64 @@ public class ClientModel { * The package that this model class belongs to. */ private final String packageName; + /** * Get the name of this model. */ private final String name; private final String fullName; + /** * Get the imports for this model. */ private final List imports; + /** * Get the description of this model. */ private final String description; + /** * Get whether this model is part of a polymorphic hierarchy. */ private final boolean isPolymorphic; + /** * Get whether this model is a parent in a polymorphic hierarchy. */ private final boolean isPolymorphicParent; + /** * Get the property that determines which polymorphic model type to create. */ private final ClientModelProperty polymorphicDiscriminator; + /** * Get the name of the property that determines which polymorphic model type to create. */ private final String polymorphicDiscriminatorName; + /** * Get the name that is used for this model when it is serialized. */ private final String serializedName; + /** * Get whether this model needs serialization flattening. */ private final boolean needsFlatten; + /** * Get the parent model of this model. */ private final String parentModelName; + /** * Get the models that derive from this model. */ private final List derivedModels; + /** * Get the name that will be used for this model's XML element representation. */ diff --git a/javagen/src/main/java/com/azure/autorest/model/clientmodel/ClientModelProperty.java b/javagen/src/main/java/com/azure/autorest/model/clientmodel/ClientModelProperty.java index 998e86ea76..541aed3478 100644 --- a/javagen/src/main/java/com/azure/autorest/model/clientmodel/ClientModelProperty.java +++ b/javagen/src/main/java/com/azure/autorest/model/clientmodel/ClientModelProperty.java @@ -11,7 +11,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Set; @@ -301,7 +301,7 @@ public final void addImportsTo(Set imports, boolean shouldGenerateXmlSer imports.add(JsonIgnore.class.getName()); imports.add(JsonAnySetter.class.getName()); imports.add(JsonAnyGetter.class.getName()); - imports.add(HashMap.class.getName()); + imports.add(LinkedHashMap.class.getName()); } if (settings.getClientFlattenAnnotationTarget() == JavaSettings.ClientFlattenAnnotationTarget.FIELD && needsFlatten) { diff --git a/javagen/src/main/java/com/azure/autorest/model/clientmodel/ClientModelPropertyReference.java b/javagen/src/main/java/com/azure/autorest/model/clientmodel/ClientModelPropertyReference.java index 663453e41b..ee7c74c860 100644 --- a/javagen/src/main/java/com/azure/autorest/model/clientmodel/ClientModelPropertyReference.java +++ b/javagen/src/main/java/com/azure/autorest/model/clientmodel/ClientModelPropertyReference.java @@ -24,10 +24,8 @@ public class ClientModelPropertyReference implements ClientModelPropertyAccess { private final ClientModel targetModel; private final ClientModelProperty targetProperty; - private ClientModelPropertyReference(ClientModelProperty targetProperty, - ClientModel targetModel, - ClientModelPropertyAccess referenceProperty, - String name) { + private ClientModelPropertyReference(ClientModelProperty targetProperty, ClientModel targetModel, + ClientModelPropertyAccess referenceProperty, String name) { this.targetProperty = targetProperty; this.targetModel = targetModel; this.referenceProperty = referenceProperty; @@ -46,16 +44,12 @@ public static ClientModelPropertyReference ofParentProperty(ClientModelPropertyR } public static ClientModelPropertyReference ofFlattenProperty(ClientModelProperty targetProperty, - ClientModel targetModel, - ClientModelProperty property, - String name) { + ClientModel targetModel, ClientModelProperty property, String name) { return new ClientModelPropertyReference(targetProperty, targetModel, property, name); } public static ClientModelPropertyReference ofFlattenProperty(ClientModelProperty targetProperty, - ClientModel targetModel, - ClientModelPropertyReference referenceProperty, - String name) { + ClientModel targetModel, ClientModelPropertyReference referenceProperty, String name) { if (!referenceProperty.isFromFlattenedProperty()) { throw new IllegalArgumentException("Property is not from flattened model: " + referenceProperty.getName()); } @@ -88,7 +82,8 @@ public List getAllProperties() { } else if (referenceProperty instanceof ClientModelPropertyReference) { properties.addAll(((ClientModelPropertyReference) referenceProperty).getAllProperties()); } else { - throw new IllegalStateException("Unknown subclass of ClientModelPropertyAccess: " + referenceProperty.getClass().getName()); + throw new IllegalStateException( + "Unknown subclass of ClientModelPropertyAccess: " + referenceProperty.getClass().getName()); } return properties; } @@ -109,7 +104,8 @@ public String getDescription() { @Override public String getGetterName() { - return CodeNamer.getModelNamer().modelPropertyGetterName(this.referenceProperty.getClientType(), this.getName()); + return CodeNamer.getModelNamer() + .modelPropertyGetterName(this.referenceProperty.getClientType(), this.getName()); } @Override @@ -149,7 +145,8 @@ public boolean isRequired() { @Override public boolean isRequiredForCreate() { - return (targetProperty == null || targetProperty.isRequiredForCreate()) && referenceProperty.isRequiredForCreate(); + return (targetProperty == null || targetProperty.isRequiredForCreate()) + && referenceProperty.isRequiredForCreate(); } @Override diff --git a/javagen/src/main/java/com/azure/autorest/template/JsonMergePatchHelperTemplate.java b/javagen/src/main/java/com/azure/autorest/template/JsonMergePatchHelperTemplate.java index c3f4ba7a44..aba6defda2 100644 --- a/javagen/src/main/java/com/azure/autorest/template/JsonMergePatchHelperTemplate.java +++ b/javagen/src/main/java/com/azure/autorest/template/JsonMergePatchHelperTemplate.java @@ -5,15 +5,19 @@ import com.azure.autorest.extension.base.plugin.JavaSettings; import com.azure.autorest.model.clientmodel.ClientModel; +import com.azure.autorest.model.clientmodel.ClientModelProperty; import com.azure.autorest.model.javamodel.JavaClass; import com.azure.autorest.model.javamodel.JavaFile; import com.azure.autorest.model.javamodel.JavaVisibility; import com.azure.autorest.util.ClientModelUtil; import com.azure.autorest.util.CodeNamer; +import com.azure.core.util.CoreUtils; import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Set; +import java.util.stream.Collectors; public class JsonMergePatchHelperTemplate implements IJavaTemplate, JavaFile>{ @@ -71,13 +75,25 @@ private static void createJsonMergePatchAccessHelpers(List models, } for (ClientModel model : models) { - if (model.getParentModelName() != null && !model.getParentModelName().isEmpty()) { + if (!model.getImplementationDetails().isInput()) { + // Model is only used as output and doesn't need to support json-merge-patch. + continue; + } + + if (model.isPolymorphic() && CoreUtils.isNullOrEmpty(model.getDerivedModels())) { // Only polymorphic parent models generate an accessor. + // If it is the super most parent model, it will generate the prepareModelForJsonMergePatch method. + // Other parents need to generate setters for the properties that are used in json-merge-patch, used in + // deserialization to prevent these properties from always being included in serialization. continue; } - if (!model.getImplementationDetails().isInput()) { - // Model is only used as output and doesn't need to support json-merge-patch. + List setterProperties = model.getProperties().stream() + .filter(property -> !property.isConstant() && !property.isPolymorphicDiscriminator()) + .collect(Collectors.toList()); + + if (!CoreUtils.isNullOrEmpty(model.getParentModelName()) && setterProperties.isEmpty()) { + // Model isn't the root parent and doesn't have any setter properties, no need to generate an accessor. continue; } @@ -85,20 +101,41 @@ private static void createJsonMergePatchAccessHelpers(List models, String camelModelName = CodeNamer.toCamelCase(modelName); // Accessor field declaration. - javaClass.privateMemberVariable(String.format("static %sAccessor %sAccessor", modelName, camelModelName)); + javaClass.privateMemberVariable("static " + modelName + "Accessor " + camelModelName + "Accessor"); // Accessor interface declaration. - javaClass.interfaceBlock(JavaVisibility.Public, String.format("%sAccessor", modelName), - interfaceBlock -> interfaceBlock.publicMethod( - String.format("%1$s prepareModelForJsonMergePatch(%1$s %2$s, boolean jsonMergePatchEnabled)", - modelName, camelModelName))); + javaClass.interfaceBlock(JavaVisibility.Public, modelName + "Accessor", interfaceBlock -> { + if (CoreUtils.isNullOrEmpty(model.getParentModelName())) { + // Only the super most parent model generates the prepareModelForJsonMergePatch method. + interfaceBlock.publicMethod( + modelName + " prepareModelForJsonMergePatch(" + modelName + " " + camelModelName + + ", boolean jsonMergePatchEnabled)"); + + interfaceBlock.publicMethod("boolean isJsonMergePatch(" + modelName + " " + camelModelName + ")"); + } + + if (model.isPolymorphicParent()) { + String modelNameParameter = model.getName().substring(0, 1).toLowerCase(Locale.ROOT) + + model.getName().substring(1); + for (ClientModelProperty property : model.getProperties()) { + if (property.isConstant() || property.isPolymorphicDiscriminator()) { + // Don't generate setters for constant or discriminator properties. + continue; + } + + interfaceBlock.publicMethod("void " + property.getSetterName() + "(" + + model.getName() + " " + modelNameParameter + ", " + + property.getClientType() + " " + property.getName() + ")"); + } + } + }); // Accessor field setter. - javaClass.publicStaticMethod(String.format("void set%1$sAccessor(%1$sAccessor accessor)", modelName), + javaClass.publicStaticMethod("void set" + modelName + "Accessor(" + modelName + "Accessor accessor)", methodBlock -> methodBlock.line(camelModelName + "Accessor = accessor;")); // Accessor field getter. - javaClass.publicStaticMethod(String.format("%1$sAccessor get%1$sAccessor()", modelName), + javaClass.publicStaticMethod(modelName + "Accessor get" + modelName + "Accessor()", methodBlock -> methodBlock.methodReturn(camelModelName + "Accessor")); } } diff --git a/javagen/src/main/java/com/azure/autorest/template/ModelTemplate.java b/javagen/src/main/java/com/azure/autorest/template/ModelTemplate.java index 28e2d42ad8..1cb0f6d1fe 100644 --- a/javagen/src/main/java/com/azure/autorest/template/ModelTemplate.java +++ b/javagen/src/main/java/com/azure/autorest/template/ModelTemplate.java @@ -602,18 +602,7 @@ private void addProperties(ClientModel model, JavaClass classBlock, JavaSettings if (ClientModelUtil.includePropertyInConstructor(property, settings)) { classBlock.privateFinalMemberVariable(fieldSignature); } else { - if (model.isPolymorphicParent() && settings.isStreamStyleSerialization() - && model.getImplementationDetails().getUsages().contains(ImplementationDetails.Usage.JSON_MERGE_PATCH)) { - // Polymorphic parents in stream-style serialization used for json-merge-patch generate a - // package-private field to support setting the value without needing to use a setter. This is done - // as the setter performs a dual action of setting the property and determining whether the property - // is serialized in the patch request. - // This forces generated SDKs to include all models in the polymorphic hierarchy in the same - // package. - classBlock.variable(fieldSignature, JavaVisibility.PackagePrivate); - } else { - classBlock.privateMemberVariable(fieldSignature); - } + classBlock.privateMemberVariable(fieldSignature); } } } @@ -1269,35 +1258,71 @@ private void addJsonMergePatchRelatedPropertyAndAccessors(JavaClass classBlock, return; } - // Only the root model needs to have the jsonMergePatch property and accessors. - boolean rootParent = model.getParentModelName() == null || model.getParentModelName().isEmpty(); - if (rootParent) { - // properties - addGeneratedAnnotation(classBlock); - classBlock.privateMemberVariable("boolean jsonMergePatch"); - - addGeneratedAnnotation(classBlock); - classBlock.method(JavaVisibility.PackagePrivate, null, "boolean isJsonMergePatch()", - method -> method.line("return this.jsonMergePatch;")); - } - classBlock.javadocComment(comment -> comment.description("Stores updated model property, the value is property name, not serialized name")); addGeneratedAnnotation(classBlock); classBlock.privateFinalMemberVariable("Set updatedProperties = new HashSet<>()"); + if (model.isPolymorphic() && CoreUtils.isNullOrEmpty(model.getDerivedModels())) { + // Only polymorphic parent models generate an accessor. + // If it is the super most parent model, it will generate the prepareModelForJsonMergePatch method. + // Other parents need to generate setters for the properties that are used in json-merge-patch, used in + // deserialization to prevent these properties from always being included in serialization. + return; + } + + List setterProperties = !model.isPolymorphic() ? Collections.emptyList() + : model.getProperties().stream() + .filter(property -> !property.isConstant() && !property.isPolymorphicDiscriminator()) + .collect(Collectors.toList()); + + boolean rootParent = CoreUtils.isNullOrEmpty(model.getParentModelName()); + if (!rootParent && setterProperties.isEmpty()) { + // Model isn't the root parent and doesn't have any setter properties, no need to generate an accessor. + return; + } + + if (rootParent) { + // Only the root model needs to have the jsonMergePatch property. + addGeneratedAnnotation(classBlock); + classBlock.privateMemberVariable("boolean jsonMergePatch"); + } + if (rootParent) { // setter addGeneratedAnnotation(classBlock); classBlock.privateMethod("void serializeAsJsonMergePatch(boolean jsonMergePatch)", method -> method.line("this.jsonMergePatch = jsonMergePatch;")); - - // static code block to access jsonMergePatch setter - classBlock.staticBlock(staticBlock -> staticBlock.text(String.format( - "JsonMergePatchHelper.set%sAccessor((model, jsonMergePatchEnabled) -> {\n" - + "model.serializeAsJsonMergePatch(jsonMergePatchEnabled);\n" + "return model;\n" + "});", - model.getName()))); } + + // static code block to access jsonMergePatch setter + classBlock.staticBlock(staticBlock -> { + String accessorName = model.getName() + "Accessor"; + staticBlock.line("JsonMergePatchHelper.set" + accessorName + "(new JsonMergePatchHelper." + accessorName + "() {"); + staticBlock.indent(() -> { + if (rootParent) { + staticBlock.line("@Override"); + staticBlock.block("public " + model.getName() + " prepareModelForJsonMergePatch(" + model.getName() + + " model, boolean jsonMergePatchEnabled)", setJsonMergePatch -> { + staticBlock.line("model.serializeAsJsonMergePatch(jsonMergePatchEnabled);"); + staticBlock.line("return model;"); + }); + + staticBlock.line("@Override"); + staticBlock.block("public boolean isJsonMergePatch(" + model.getName() + " model)", + getJsonMergePatch -> getJsonMergePatch.line("return model.jsonMergePatch;")); + } + + for (ClientModelProperty setter : setterProperties) { + staticBlock.line("@Override"); + staticBlock.block("public void " + setter.getSetterName() + "(" + model.getName() + + " model, " + setter.getWireType() + " " + setter.getName() + ")", + setField -> setField.line("model." + setter.getName() + " = " + setter.getName() + ";")); + } + }); + + staticBlock.line("});"); + }); } private static boolean modelDefinesProperty(ClientModel model, ClientModelProperty property) { diff --git a/javagen/src/main/java/com/azure/autorest/template/StreamSerializationModelTemplate.java b/javagen/src/main/java/com/azure/autorest/template/StreamSerializationModelTemplate.java index 9c89d061a4..e835c561a6 100644 --- a/javagen/src/main/java/com/azure/autorest/template/StreamSerializationModelTemplate.java +++ b/javagen/src/main/java/com/azure/autorest/template/StreamSerializationModelTemplate.java @@ -43,6 +43,7 @@ import java.util.function.Consumer; import java.util.stream.Collectors; +import static com.azure.autorest.util.ClientModelUtil.JSON_MERGE_PATCH_HELPER_CLASS_NAME; import static com.azure.autorest.util.ClientModelUtil.includePropertyInConstructor; /** @@ -54,6 +55,9 @@ public class StreamSerializationModelTemplate extends ModelTemplate { // TODO (alzimmer): Future enhancements: // - Create a utility class in the implementation package containing base serialization for polymorphic types. // This will enable a central location for shared logic, reducing package size and hopefully JIT optimizations. + // - Convert all logic in this class to an instance type that is created with the ClientModel being generated. + // This will simplify all the APIs to just taking that type rather than passing bits of information from here + // and there everywhere, which require extensive changes each time a new feature is added. protected StreamSerializationModelTemplate() { } @@ -242,7 +246,14 @@ private static void writeToJson(JavaClass classBlock, ClientModelPropertiesManag classBlock.annotation("Override"); classBlock.publicMethod("JsonWriter toJson(JsonWriter jsonWriter) throws IOException", methodBlock -> { if (isJsonMergePatch) { - methodBlock.ifBlock("isJsonMergePatch()", ifBlock -> ifBlock.methodReturn("toJsonMergePatch(jsonWriter)")) + // If the model is the root parent use the JSON merge patch serialization tracking property directly, + // otherwise use the access helper to determine whether to use JSON merge patch serialization. + ClientModel rootParent = ClientModelUtil.getRootParent(propertiesManager.getModel()); + String ifStatement = (rootParent == propertiesManager.getModel()) + ? "jsonMergePatch" + : JSON_MERGE_PATCH_HELPER_CLASS_NAME + ".get" + rootParent.getName() + "Accessor().isJsonMergePatch(this)"; + + methodBlock.ifBlock(ifStatement, ifBlock -> ifBlock.methodReturn("toJsonMergePatch(jsonWriter)")) .elseBlock(elseBlock -> serializeJsonProperties(methodBlock, propertiesManager, false)); } else { serializeJsonProperties(methodBlock, propertiesManager, false); @@ -341,13 +352,10 @@ private static void serializeJsonProperty(JavaBlock methodBlock, ClientModelProp if (isJsonMergePatch) { if (property.getClientType().isNullable()) { - methodBlock.ifBlock(String.format("updatedProperties.contains(\"%s\")", property.getName()), codeBlock -> { - codeBlock.ifBlock(String.format("%s == null", getPropertyGetterStatement(property, fromSuperType)), ifBlock -> { - ifBlock.line(String.format("jsonWriter.writeNullField(\"%s\");", property.getSerializedName())); - }).elseBlock(elseBlock -> { - serializeJsonProperty(codeBlock, property, serializedName, fromSuperType, isJsonMergePatch); - }); - }); + methodBlock.ifBlock("updatedProperties.contains(\"" + property.getName() + "\")", codeBlock -> + codeBlock.ifBlock(getPropertyGetterStatement(property, fromSuperType) + " == null", + ifBlock -> ifBlock.line("jsonWriter.writeNullField(\"" + property.getSerializedName() + "\");")) + .elseBlock(elseBlock -> serializeJsonProperty(codeBlock, property, serializedName, fromSuperType, isJsonMergePatch))); } else { serializeJsonProperty(methodBlock, property, serializedName, fromSuperType, isJsonMergePatch); } @@ -480,17 +488,15 @@ private static void serializeJsonContainerProperty(JavaBlock methodBlock, String methodBlock.indent(() -> { if (valueSerializationMethod != null) { if (isJsonMergePatch && containerType instanceof MapType) { - methodBlock.block("", codeBlock -> { - codeBlock.ifBlock(elementName + "!=null", ifBlock -> { - if (elementType instanceof ClassType && ((ClassType) elementType).isSwaggerType()) { - methodBlock.line("JsonMergePatchHelper.get" + ((ClassType) elementType).getName() + "Accessor().prepareModelForJsonMergePatch(" + elementName + ", true);"); - } - ifBlock.line(valueSerializationMethod + ";"); - if (elementType instanceof ClassType && ((ClassType) elementType).isSwaggerType()) { - methodBlock.line("JsonMergePatchHelper.get" + ((ClassType) elementType).getName() + "Accessor().prepareModelForJsonMergePatch(" + elementName + ", false);"); - } - }).elseBlock(elseBlock -> elseBlock.line(lambdaWriterName + ".writeNull();")); - }); + methodBlock.block("", codeBlock -> codeBlock.ifBlock(elementName + "!= null", ifBlock -> { + if (elementType instanceof ClassType && ((ClassType) elementType).isSwaggerType()) { + methodBlock.line("JsonMergePatchHelper.get" + ((ClassType) elementType).getName() + "Accessor().prepareModelForJsonMergePatch(" + elementName + ", true);"); + } + ifBlock.line(valueSerializationMethod + ";"); + if (elementType instanceof ClassType && ((ClassType) elementType).isSwaggerType()) { + methodBlock.line("JsonMergePatchHelper.get" + ((ClassType) elementType).getName() + "Accessor().prepareModelForJsonMergePatch(" + elementName + ", false);"); + } + }).elseBlock(elseBlock -> elseBlock.line(lambdaWriterName + ".writeNull();"))); } else { methodBlock.line(valueSerializationMethod); } @@ -543,7 +549,7 @@ private static void serializeJsonContainerProperty(JavaBlock methodBlock, String * * @param methodBlock The method handling serialization. * @param flattenedProperties The flattened properties structure. - * @param isJsonMergePatch Whether or not the serialization is for a JSON merge patch model. + * @param isJsonMergePatch Whether the serialization is for a JSON merge patch model. */ private static void handleFlattenedPropertiesSerialization(JavaBlock methodBlock, JsonFlattenedPropertiesTree flattenedProperties, boolean isJsonMergePatch) { @@ -760,9 +766,10 @@ private static void writeFromJsonDeserialization(JavaBlock methodBlock, AtomicReference ifBlockReference = new AtomicReference<>(null); BiConsumer consumer = (property, fromSuper) -> - handleJsonPropertyDeserialization(property, propertiesManager.getDeserializedModelName(), - whileBlock, ifBlockReference, fieldNameVariableName, fromSuper, - propertiesManager.hasConstructorArguments(), settings, polymorphicJsonMergePatchScenario); + handleJsonPropertyDeserialization(propertiesManager.getModel(), property, + propertiesManager.getDeserializedModelName(), whileBlock, ifBlockReference, + fieldNameVariableName, fromSuper, propertiesManager.hasConstructorArguments(), settings, + polymorphicJsonMergePatchScenario); // Constants are skipped as they aren't deserialized. propertiesManager.forEachSuperRequiredProperty(property -> { @@ -960,9 +967,9 @@ private static void addReaderWhileLoop(JavaBlock methodBlock, boolean initialize }); } - private static void handleJsonPropertyDeserialization(ClientModelProperty property, String modelVariableName, - JavaBlock methodBlock, AtomicReference ifBlockReference, String fieldNameVariableName, - boolean fromSuper, boolean hasConstructorArguments, JavaSettings settings, + private static void handleJsonPropertyDeserialization(ClientModel model, ClientModelProperty property, + String modelVariableName, JavaBlock methodBlock, AtomicReference ifBlockReference, + String fieldNameVariableName, boolean fromSuper, boolean hasConstructorArguments, JavaSettings settings, boolean polymorphicJsonMergePatchScenario) { // Property will be handled later by flattened deserialization. if (property.getNeedsFlatten()) { @@ -970,23 +977,24 @@ private static void handleJsonPropertyDeserialization(ClientModelProperty proper } JavaIfBlock ifBlock = ifBlockReference.get(); - ifBlock = handleJsonPropertyDeserialization(property, modelVariableName, methodBlock, ifBlock, + ifBlock = handleJsonPropertyDeserialization(model, property, modelVariableName, methodBlock, ifBlock, fieldNameVariableName, fromSuper, hasConstructorArguments, settings, polymorphicJsonMergePatchScenario); ifBlockReference.set(ifBlock); } - private static JavaIfBlock handleJsonPropertyDeserialization(ClientModelProperty property, String modelVariableName, - JavaBlock methodBlock, JavaIfBlock ifBlock, String fieldNameVariableName, boolean fromSuper, - boolean hasConstructorArguments, JavaSettings settings, boolean polymorphicJsonMergePatchScenario) { + private static JavaIfBlock handleJsonPropertyDeserialization(ClientModel model, ClientModelProperty property, + String modelVariableName, JavaBlock methodBlock, JavaIfBlock ifBlock, String fieldNameVariableName, + boolean fromSuper, boolean hasConstructorArguments, JavaSettings settings, + boolean polymorphicJsonMergePatchScenario) { String jsonPropertyName = property.getSerializedName(); if (CoreUtils.isNullOrEmpty(jsonPropertyName)) { return ifBlock; } return ifOrElseIf(methodBlock, ifBlock, "\"" + jsonPropertyName + "\".equals(" + fieldNameVariableName + ")", - deserializationBlock -> generateJsonDeserializationLogic(deserializationBlock, modelVariableName, property, - fromSuper, hasConstructorArguments, settings, polymorphicJsonMergePatchScenario)); + deserializationBlock -> generateJsonDeserializationLogic(deserializationBlock, modelVariableName, model, + property, fromSuper, hasConstructorArguments, settings, polymorphicJsonMergePatchScenario)); } private static void handleFlattenedPropertiesDeserialization( @@ -1012,8 +1020,9 @@ private static JavaIfBlock handleFlattenedPropertiesDeserializationHelper( return ifOrElseIf(methodBlock, ifBlock, "\"" + flattenedProperties.getNodeName() + "\".equals(" + fieldNameVariableName + ")", deserializationBlock -> generateJsonDeserializationLogic(deserializationBlock, modelVariableName, - propertyWithMetadata.getProperty(), propertyWithMetadata.isFromSuperClass(), - hasConstructorArguments, settings, polymorphicJsonMergePatchScenario)); + propertyWithMetadata.getModel(), propertyWithMetadata.getProperty(), + propertyWithMetadata.isFromSuperClass(), hasConstructorArguments, settings, + polymorphicJsonMergePatchScenario)); } else { // Otherwise this is an intermediate location and a while loop reader needs to be added. return ifOrElseIf(methodBlock, ifBlock, @@ -1033,7 +1042,7 @@ private static JavaIfBlock handleFlattenedPropertiesDeserializationHelper( } private static void generateJsonDeserializationLogic(JavaBlock deserializationBlock, String modelVariableName, - ClientModelProperty property, boolean fromSuper, boolean hasConstructorArguments, JavaSettings settings, + ClientModel model, ClientModelProperty property, boolean fromSuper, boolean hasConstructorArguments, JavaSettings settings, boolean polymorphicJsonMergePatchScenario) { IType wireType = property.getWireType(); IType clientType = property.getClientType(); @@ -1048,7 +1057,7 @@ private static void generateJsonDeserializationLogic(JavaBlock deserializationBl && (includePropertyInConstructor(property, settings) || (fromSuper && !property.isReadOnly())); BiConsumer simpleDeserializationConsumer = (logic, block) -> { if (!hasConstructorArguments) { - handleSettingDeserializedValue(block, modelVariableName, property, logic, fromSuper, + handleSettingDeserializedValue(block, modelVariableName, model, property, logic, fromSuper, polymorphicJsonMergePatchScenario); } else { block.line(property.getName() + " = " + logic + ";"); @@ -1079,7 +1088,7 @@ private static void generateJsonDeserializationLogic(JavaBlock deserializationBl } } else if (wireType == ClassType.OBJECT) { if (!hasConstructorArguments) { - handleSettingDeserializedValue(deserializationBlock, modelVariableName, property, + handleSettingDeserializedValue(deserializationBlock, modelVariableName, model, property, "reader.readUntyped()", fromSuper, polymorphicJsonMergePatchScenario); } else { deserializationBlock.line(property.getName() + " = reader.readUntyped();"); @@ -1094,8 +1103,8 @@ private static void generateJsonDeserializationLogic(JavaBlock deserializationBl ((IterableType) wireType).getElementType(), ((IterableType) clientType).getElementType(), 0); if (!hasConstructorArguments) { - handleSettingDeserializedValue(deserializationBlock, modelVariableName, property, property.getName(), - fromSuper, polymorphicJsonMergePatchScenario); + handleSettingDeserializedValue(deserializationBlock, modelVariableName, model, property, + property.getName(), fromSuper, polymorphicJsonMergePatchScenario); } } else if (wireType instanceof MapType) { if (!hasConstructorArguments) { @@ -1109,8 +1118,8 @@ private static void generateJsonDeserializationLogic(JavaBlock deserializationBl ((MapType) wireType).getValueType(), ((MapType) clientType).getValueType(), 0); if (!hasConstructorArguments) { - handleSettingDeserializedValue(deserializationBlock, modelVariableName, property, property.getName(), - fromSuper, polymorphicJsonMergePatchScenario); + handleSettingDeserializedValue(deserializationBlock, modelVariableName, model, property, + property.getName(), fromSuper, polymorphicJsonMergePatchScenario); } } else { // TODO (alzimmer): Resolve this as deserialization logic generation needs to handle all cases. @@ -1315,8 +1324,9 @@ private static void createObjectAndReturn(JavaBlock methodBlock, String modelNam + "(" + constructorArgs + ");"); BiConsumer handleSettingDeserializedValue = (property, fromSuper) -> - handleSettingDeserializedValue(methodBlock, propertiesManager.getDeserializedModelName(), property, - property.getName(), fromSuper, polymorphicJsonMergePatchScenario); + handleSettingDeserializedValue(methodBlock, propertiesManager.getDeserializedModelName(), + propertiesManager.getModel(), property, property.getName(), fromSuper, + polymorphicJsonMergePatchScenario); propertiesManager.forEachSuperReadOnlyProperty(property -> handleSettingDeserializedValue.accept(property, true)); propertiesManager.forEachSuperSetterProperty(property -> handleSettingDeserializedValue.accept(property, true)); @@ -1326,12 +1336,13 @@ private static void createObjectAndReturn(JavaBlock methodBlock, String modelNam if (propertiesManager.getAdditionalProperties() != null) { handleSettingDeserializedValue(methodBlock, propertiesManager.getDeserializedModelName(), - propertiesManager.getAdditionalProperties(), propertiesManager.getAdditionalProperties().getName(), - false, polymorphicJsonMergePatchScenario); + propertiesManager.getModel(), propertiesManager.getAdditionalProperties(), + propertiesManager.getAdditionalProperties().getName(), false, polymorphicJsonMergePatchScenario); } else if (propertiesManager.getSuperAdditionalPropertiesProperty() != null) { handleSettingDeserializedValue(methodBlock, propertiesManager.getDeserializedModelName(), - propertiesManager.getSuperAdditionalPropertiesProperty(), propertiesManager.getSuperAdditionalPropertiesProperty().getName(), - true, polymorphicJsonMergePatchScenario); + propertiesManager.getModel(), propertiesManager.getSuperAdditionalPropertiesProperty(), + propertiesManager.getSuperAdditionalPropertiesProperty().getName(), true, + polymorphicJsonMergePatchScenario); } methodBlock.line(); @@ -1391,16 +1402,41 @@ private static void addFoundValidationIfCheck(JavaBlock methodBlock, ClientModel } private static void handleSettingDeserializedValue(JavaBlock methodBlock, String modelVariableName, - ClientModelProperty property, String value, boolean fromSuper, boolean polymorphicJsonMergePatchScenario) { + ClientModel model, ClientModelProperty property, String value, boolean fromSuper, + boolean polymorphicJsonMergePatchScenario) { // If the property is defined in a super class use the setter as this will be able to set the value in the // super class. - if (fromSuper && !polymorphicJsonMergePatchScenario) { - methodBlock.line(modelVariableName + "." + property.getSetterName() + "(" + value + ");"); + if (fromSuper) { + if (polymorphicJsonMergePatchScenario) { + // Polymorphic JSON merge patch needs special handling as the setter methods are used to track whether + // the property is included in patch serialization. To prevent deserialization from requiring parent + // defined properties to always be included in serialization, access helpers are used to set the value + // without marking the property as included in the patch. + ClientModel definingModel = definingModel(model, property); + methodBlock.line("JsonMergePatchHelper.get" + definingModel.getName() + "Accessor()." + + property.getSetterName() + "(" + modelVariableName + ", " + value + ");"); + } else { + methodBlock.line(modelVariableName + "." + property.getSetterName() + "(" + value + ");"); + } } else { methodBlock.line(modelVariableName + "." + property.getName() + " = " + value + ";"); } } + // TODO (alzimmer): This is a very inefficient design where we're using the ClientModelProperty to find which model + // in the polymorphic hierarchy defines it, but this is a simple bootstrapping method rather than a larger + // re-architecting. + private static ClientModel definingModel(ClientModel model, ClientModelProperty property) { + while (model != null) { + if (model.getProperties().stream().anyMatch(prop -> Objects.equals(prop.getName(), property.getName()))) { + return model; + } + model = ClientModelUtil.getClientModel(model.getParentModelName()); + } + + throw new IllegalStateException("No ClientModel in the polymorphic hierarchy define this property, this should never happen."); + } + private static boolean isSuperTypeWithDiscriminator(ClientModel model) { return !CoreUtils.isNullOrEmpty(model.getPolymorphicDiscriminatorName()) && !CoreUtils.isNullOrEmpty(model.getDerivedModels()); @@ -1850,8 +1886,8 @@ private static void deserializeXmlAttribute(JavaBlock methodBlock, ClientModelPr if (propertiesManager.hasConstructorArguments()) { methodBlock.line("%s %s = %s;", attribute.getClientType(), attribute.getName(), xmlAttributeDeserialization); } else { - handleSettingDeserializedValue(methodBlock, propertiesManager.getDeserializedModelName(), attribute, - xmlAttributeDeserialization, fromSuper, false); + handleSettingDeserializedValue(methodBlock, propertiesManager.getDeserializedModelName(), + propertiesManager.getModel(), attribute, xmlAttributeDeserialization, fromSuper, false); } } @@ -1861,8 +1897,8 @@ private static void deserializeXmlText(JavaBlock methodBlock, ClientModelPropert if (propertiesManager.hasConstructorArguments()) { methodBlock.line(text.getClientType() + " " + text.getName() + " = " + xmlTextDeserialization + ";"); } else { - handleSettingDeserializedValue(methodBlock, propertiesManager.getDeserializedModelName(), text, - xmlTextDeserialization, fromSuper, false); + handleSettingDeserializedValue(methodBlock, propertiesManager.getDeserializedModelName(), + propertiesManager.getModel(), text, xmlTextDeserialization, fromSuper, false); } } @@ -1911,7 +1947,7 @@ private static void generateXmlDeserializationLogic(JavaBlock deserializationBlo deserializationBlock.line(property.getName() + " = " + simpleDeserialization + ";"); } else { handleSettingDeserializedValue(deserializationBlock, propertiesManager.getDeserializedModelName(), - property, simpleDeserialization, fromSuper, false); + propertiesManager.getModel(), property, simpleDeserialization, fromSuper, false); } } else if (wireType instanceof IterableType) { IType elementType = ((IterableType) wireType).getElementType(); diff --git a/javagen/src/main/java/com/azure/autorest/util/ClientModelUtil.java b/javagen/src/main/java/com/azure/autorest/util/ClientModelUtil.java index ec9177ca0e..698c0da133 100644 --- a/javagen/src/main/java/com/azure/autorest/util/ClientModelUtil.java +++ b/javagen/src/main/java/com/azure/autorest/util/ClientModelUtil.java @@ -460,7 +460,7 @@ public static boolean isOutputOnly(ClientModel model) { */ public static boolean isJsonMergePatchModel(ClientModel model) { return model.getImplementationDetails() != null && model.getImplementationDetails().getUsages() != null - && model.getImplementationDetails().getUsages().contains(ImplementationDetails.Usage.JSON_MERGE_PATCH); + && model.getImplementationDetails().getUsages().contains(ImplementationDetails.Usage.JSON_MERGE_PATCH); } /** diff --git a/typespec-tests/src/main/java/com/_specs_/azure/core/basic/implementation/JsonMergePatchHelper.java b/typespec-tests/src/main/java/com/_specs_/azure/core/basic/implementation/JsonMergePatchHelper.java index c57946cee0..cf80bc6695 100644 --- a/typespec-tests/src/main/java/com/_specs_/azure/core/basic/implementation/JsonMergePatchHelper.java +++ b/typespec-tests/src/main/java/com/_specs_/azure/core/basic/implementation/JsonMergePatchHelper.java @@ -15,6 +15,8 @@ public class JsonMergePatchHelper { public interface UserAccessor { User prepareModelForJsonMergePatch(User user, boolean jsonMergePatchEnabled); + + boolean isJsonMergePatch(User user); } public static void setUserAccessor(UserAccessor accessor) { @@ -29,6 +31,8 @@ public static UserAccessor getUserAccessor() { public interface UserOrderAccessor { UserOrder prepareModelForJsonMergePatch(UserOrder userOrder, boolean jsonMergePatchEnabled); + + boolean isJsonMergePatch(UserOrder userOrder); } public static void setUserOrderAccessor(UserOrderAccessor accessor) { diff --git a/typespec-tests/src/main/java/com/_specs_/azure/core/basic/models/FirstItem.java b/typespec-tests/src/main/java/com/_specs_/azure/core/basic/models/FirstItem.java index 615a4299dc..103d97e227 100644 --- a/typespec-tests/src/main/java/com/_specs_/azure/core/basic/models/FirstItem.java +++ b/typespec-tests/src/main/java/com/_specs_/azure/core/basic/models/FirstItem.java @@ -62,19 +62,17 @@ public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { @Generated public static FirstItem fromJson(JsonReader jsonReader) throws IOException { return jsonReader.readObject(reader -> { - int id = 0; + FirstItem deserializedFirstItem = new FirstItem(); while (reader.nextToken() != JsonToken.END_OBJECT) { String fieldName = reader.getFieldName(); reader.nextToken(); if ("id".equals(fieldName)) { - id = reader.getInt(); + deserializedFirstItem.id = reader.getInt(); } else { reader.skipChildren(); } } - FirstItem deserializedFirstItem = new FirstItem(); - deserializedFirstItem.id = id; return deserializedFirstItem; }); diff --git a/typespec-tests/src/main/java/com/_specs_/azure/core/basic/models/SecondItem.java b/typespec-tests/src/main/java/com/_specs_/azure/core/basic/models/SecondItem.java index fa733e229e..f892d31306 100644 --- a/typespec-tests/src/main/java/com/_specs_/azure/core/basic/models/SecondItem.java +++ b/typespec-tests/src/main/java/com/_specs_/azure/core/basic/models/SecondItem.java @@ -62,19 +62,17 @@ public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { @Generated public static SecondItem fromJson(JsonReader jsonReader) throws IOException { return jsonReader.readObject(reader -> { - String name = null; + SecondItem deserializedSecondItem = new SecondItem(); while (reader.nextToken() != JsonToken.END_OBJECT) { String fieldName = reader.getFieldName(); reader.nextToken(); if ("name".equals(fieldName)) { - name = reader.getString(); + deserializedSecondItem.name = reader.getString(); } else { reader.skipChildren(); } } - SecondItem deserializedSecondItem = new SecondItem(); - deserializedSecondItem.name = name; return deserializedSecondItem; }); diff --git a/typespec-tests/src/main/java/com/_specs_/azure/core/basic/models/User.java b/typespec-tests/src/main/java/com/_specs_/azure/core/basic/models/User.java index 1d4333c048..799ba77cfa 100644 --- a/typespec-tests/src/main/java/com/_specs_/azure/core/basic/models/User.java +++ b/typespec-tests/src/main/java/com/_specs_/azure/core/basic/models/User.java @@ -45,29 +45,32 @@ public final class User implements JsonSerializable { @Generated private String etag; - @Generated - private boolean jsonMergePatch; - - @Generated - boolean isJsonMergePatch() { - return this.jsonMergePatch; - } - /** * Stores updated model property, the value is property name, not serialized name. */ @Generated private final Set updatedProperties = new HashSet<>(); + @Generated + private boolean jsonMergePatch; + @Generated private void serializeAsJsonMergePatch(boolean jsonMergePatch) { this.jsonMergePatch = jsonMergePatch; } static { - JsonMergePatchHelper.setUserAccessor((model, jsonMergePatchEnabled) -> { - model.serializeAsJsonMergePatch(jsonMergePatchEnabled); - return model; + JsonMergePatchHelper.setUserAccessor(new JsonMergePatchHelper.UserAccessor() { + @Override + public User prepareModelForJsonMergePatch(User model, boolean jsonMergePatchEnabled) { + model.serializeAsJsonMergePatch(jsonMergePatchEnabled); + return model; + } + + @Override + public boolean isJsonMergePatch(User model) { + return model.jsonMergePatch; + } }); } @@ -151,7 +154,7 @@ public String getEtag() { @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (isJsonMergePatch()) { + if (jsonMergePatch) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); @@ -193,31 +196,24 @@ private JsonWriter toJsonMergePatch(JsonWriter jsonWriter) throws IOException { @Generated public static User fromJson(JsonReader jsonReader) throws IOException { return jsonReader.readObject(reader -> { - int id = 0; - String etag = null; - String name = null; - List orders = null; + User deserializedUser = new User(); while (reader.nextToken() != JsonToken.END_OBJECT) { String fieldName = reader.getFieldName(); reader.nextToken(); if ("id".equals(fieldName)) { - id = reader.getInt(); + deserializedUser.id = reader.getInt(); } else if ("etag".equals(fieldName)) { - etag = reader.getString(); + deserializedUser.etag = reader.getString(); } else if ("name".equals(fieldName)) { - name = reader.getString(); + deserializedUser.name = reader.getString(); } else if ("orders".equals(fieldName)) { - orders = reader.readArray(reader1 -> UserOrder.fromJson(reader1)); + List orders = reader.readArray(reader1 -> UserOrder.fromJson(reader1)); + deserializedUser.orders = orders; } else { reader.skipChildren(); } } - User deserializedUser = new User(); - deserializedUser.id = id; - deserializedUser.etag = etag; - deserializedUser.name = name; - deserializedUser.orders = orders; return deserializedUser; }); diff --git a/typespec-tests/src/main/java/com/_specs_/azure/core/basic/models/UserOrder.java b/typespec-tests/src/main/java/com/_specs_/azure/core/basic/models/UserOrder.java index 231a2481ee..78b26d2161 100644 --- a/typespec-tests/src/main/java/com/_specs_/azure/core/basic/models/UserOrder.java +++ b/typespec-tests/src/main/java/com/_specs_/azure/core/basic/models/UserOrder.java @@ -38,29 +38,32 @@ public final class UserOrder implements JsonSerializable { @Generated private String detail; - @Generated - private boolean jsonMergePatch; - - @Generated - boolean isJsonMergePatch() { - return this.jsonMergePatch; - } - /** * Stores updated model property, the value is property name, not serialized name. */ @Generated private final Set updatedProperties = new HashSet<>(); + @Generated + private boolean jsonMergePatch; + @Generated private void serializeAsJsonMergePatch(boolean jsonMergePatch) { this.jsonMergePatch = jsonMergePatch; } static { - JsonMergePatchHelper.setUserOrderAccessor((model, jsonMergePatchEnabled) -> { - model.serializeAsJsonMergePatch(jsonMergePatchEnabled); - return model; + JsonMergePatchHelper.setUserOrderAccessor(new JsonMergePatchHelper.UserOrderAccessor() { + @Override + public UserOrder prepareModelForJsonMergePatch(UserOrder model, boolean jsonMergePatchEnabled) { + model.serializeAsJsonMergePatch(jsonMergePatchEnabled); + return model; + } + + @Override + public boolean isJsonMergePatch(UserOrder model) { + return model.jsonMergePatch; + } }); } @@ -135,7 +138,7 @@ public UserOrder setDetail(String detail) { @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (isJsonMergePatch()) { + if (jsonMergePatch) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); @@ -171,27 +174,21 @@ private JsonWriter toJsonMergePatch(JsonWriter jsonWriter) throws IOException { @Generated public static UserOrder fromJson(JsonReader jsonReader) throws IOException { return jsonReader.readObject(reader -> { - int id = 0; - int userId = 0; - String detail = null; + UserOrder deserializedUserOrder = new UserOrder(); while (reader.nextToken() != JsonToken.END_OBJECT) { String fieldName = reader.getFieldName(); reader.nextToken(); if ("id".equals(fieldName)) { - id = reader.getInt(); + deserializedUserOrder.id = reader.getInt(); } else if ("userId".equals(fieldName)) { - userId = reader.getInt(); + deserializedUserOrder.userId = reader.getInt(); } else if ("detail".equals(fieldName)) { - detail = reader.getString(); + deserializedUserOrder.detail = reader.getString(); } else { reader.skipChildren(); } } - UserOrder deserializedUserOrder = new UserOrder(); - deserializedUserOrder.id = id; - deserializedUserOrder.userId = userId; - deserializedUserOrder.detail = detail; return deserializedUserOrder; }); diff --git a/typespec-tests/src/main/java/com/_specs_/azure/core/traits/models/User.java b/typespec-tests/src/main/java/com/_specs_/azure/core/traits/models/User.java index 3c2a62c7f9..562f7f44a4 100644 --- a/typespec-tests/src/main/java/com/_specs_/azure/core/traits/models/User.java +++ b/typespec-tests/src/main/java/com/_specs_/azure/core/traits/models/User.java @@ -79,23 +79,19 @@ public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { @Generated public static User fromJson(JsonReader jsonReader) throws IOException { return jsonReader.readObject(reader -> { - int id = 0; - String name = null; + User deserializedUser = new User(); while (reader.nextToken() != JsonToken.END_OBJECT) { String fieldName = reader.getFieldName(); reader.nextToken(); if ("id".equals(fieldName)) { - id = reader.getInt(); + deserializedUser.id = reader.getInt(); } else if ("name".equals(fieldName)) { - name = reader.getString(); + deserializedUser.name = reader.getString(); } else { reader.skipChildren(); } } - User deserializedUser = new User(); - deserializedUser.id = id; - deserializedUser.name = name; return deserializedUser; }); diff --git a/typespec-tests/src/main/java/com/cadl/armresourceprovider/models/UserAssignedIdentities.java b/typespec-tests/src/main/java/com/cadl/armresourceprovider/models/UserAssignedIdentities.java index 8b54f8733e..2962718bf9 100644 --- a/typespec-tests/src/main/java/com/cadl/armresourceprovider/models/UserAssignedIdentities.java +++ b/typespec-tests/src/main/java/com/cadl/armresourceprovider/models/UserAssignedIdentities.java @@ -8,6 +8,7 @@ import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonIgnore; +import java.util.LinkedHashMap; import java.util.Map; /** diff --git a/typespec-tests/src/main/java/com/cadl/flatten/implementation/JsonMergePatchHelper.java b/typespec-tests/src/main/java/com/cadl/flatten/implementation/JsonMergePatchHelper.java index 4a318ec2da..da6c4f93fa 100644 --- a/typespec-tests/src/main/java/com/cadl/flatten/implementation/JsonMergePatchHelper.java +++ b/typespec-tests/src/main/java/com/cadl/flatten/implementation/JsonMergePatchHelper.java @@ -16,6 +16,8 @@ public class JsonMergePatchHelper { public interface UpdatePatchRequestAccessor { UpdatePatchRequest prepareModelForJsonMergePatch(UpdatePatchRequest updatePatchRequest, boolean jsonMergePatchEnabled); + + boolean isJsonMergePatch(UpdatePatchRequest updatePatchRequest); } public static void setUpdatePatchRequestAccessor(UpdatePatchRequestAccessor accessor) { @@ -30,6 +32,8 @@ public static UpdatePatchRequestAccessor getUpdatePatchRequestAccessor() { public interface TodoItemPatchAccessor { TodoItemPatch prepareModelForJsonMergePatch(TodoItemPatch todoItemPatch, boolean jsonMergePatchEnabled); + + boolean isJsonMergePatch(TodoItemPatch todoItemPatch); } public static void setTodoItemPatchAccessor(TodoItemPatchAccessor accessor) { diff --git a/typespec-tests/src/main/java/com/cadl/flatten/models/TodoItemPatch.java b/typespec-tests/src/main/java/com/cadl/flatten/models/TodoItemPatch.java index 0f376587b8..9da1a9d7ca 100644 --- a/typespec-tests/src/main/java/com/cadl/flatten/models/TodoItemPatch.java +++ b/typespec-tests/src/main/java/com/cadl/flatten/models/TodoItemPatch.java @@ -38,29 +38,32 @@ public final class TodoItemPatch implements JsonSerializable { @Generated private TodoItemPatchStatus status; - @Generated - private boolean jsonMergePatch; - - @Generated - boolean isJsonMergePatch() { - return this.jsonMergePatch; - } - /** * Stores updated model property, the value is property name, not serialized name. */ @Generated private final Set updatedProperties = new HashSet<>(); + @Generated + private boolean jsonMergePatch; + @Generated private void serializeAsJsonMergePatch(boolean jsonMergePatch) { this.jsonMergePatch = jsonMergePatch; } static { - JsonMergePatchHelper.setTodoItemPatchAccessor((model, jsonMergePatchEnabled) -> { - model.serializeAsJsonMergePatch(jsonMergePatchEnabled); - return model; + JsonMergePatchHelper.setTodoItemPatchAccessor(new JsonMergePatchHelper.TodoItemPatchAccessor() { + @Override + public TodoItemPatch prepareModelForJsonMergePatch(TodoItemPatch model, boolean jsonMergePatchEnabled) { + model.serializeAsJsonMergePatch(jsonMergePatchEnabled); + return model; + } + + @Override + public boolean isJsonMergePatch(TodoItemPatch model) { + return model.jsonMergePatch; + } }); } @@ -146,7 +149,7 @@ public TodoItemPatch setStatus(TodoItemPatchStatus status) { @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (isJsonMergePatch()) { + if (jsonMergePatch) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); diff --git a/typespec-tests/src/main/java/com/cadl/flatten/models/UpdatePatchRequest.java b/typespec-tests/src/main/java/com/cadl/flatten/models/UpdatePatchRequest.java index 9837112532..fc0c33a7a3 100644 --- a/typespec-tests/src/main/java/com/cadl/flatten/models/UpdatePatchRequest.java +++ b/typespec-tests/src/main/java/com/cadl/flatten/models/UpdatePatchRequest.java @@ -26,29 +26,33 @@ public final class UpdatePatchRequest implements JsonSerializable updatedProperties = new HashSet<>(); + @Generated + private boolean jsonMergePatch; + @Generated private void serializeAsJsonMergePatch(boolean jsonMergePatch) { this.jsonMergePatch = jsonMergePatch; } static { - JsonMergePatchHelper.setUpdatePatchRequestAccessor((model, jsonMergePatchEnabled) -> { - model.serializeAsJsonMergePatch(jsonMergePatchEnabled); - return model; + JsonMergePatchHelper.setUpdatePatchRequestAccessor(new JsonMergePatchHelper.UpdatePatchRequestAccessor() { + @Override + public UpdatePatchRequest prepareModelForJsonMergePatch(UpdatePatchRequest model, + boolean jsonMergePatchEnabled) { + model.serializeAsJsonMergePatch(jsonMergePatchEnabled); + return model; + } + + @Override + public boolean isJsonMergePatch(UpdatePatchRequest model) { + return model.jsonMergePatch; + } }); } @@ -89,7 +93,7 @@ public UpdatePatchRequest setPatch(TodoItemPatch patch) { @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (isJsonMergePatch()) { + if (jsonMergePatch) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); diff --git a/typespec-tests/src/main/java/com/cadl/literalservice/models/Model.java b/typespec-tests/src/main/java/com/cadl/literalservice/models/Model.java index 9630f82fb1..d37c9708b2 100644 --- a/typespec-tests/src/main/java/com/cadl/literalservice/models/Model.java +++ b/typespec-tests/src/main/java/com/cadl/literalservice/models/Model.java @@ -93,19 +93,17 @@ public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { @Generated public static Model fromJson(JsonReader jsonReader) throws IOException { return jsonReader.readObject(reader -> { - ModelOptionalLiteral optionalLiteral = null; + Model deserializedModel = new Model(); while (reader.nextToken() != JsonToken.END_OBJECT) { String fieldName = reader.getFieldName(); reader.nextToken(); if ("optionalLiteral".equals(fieldName)) { - optionalLiteral = ModelOptionalLiteral.fromString(reader.getString()); + deserializedModel.optionalLiteral = ModelOptionalLiteral.fromString(reader.getString()); } else { reader.skipChildren(); } } - Model deserializedModel = new Model(); - deserializedModel.optionalLiteral = optionalLiteral; return deserializedModel; }); diff --git a/typespec-tests/src/main/java/com/cadl/longrunning/models/JobResult.java b/typespec-tests/src/main/java/com/cadl/longrunning/models/JobResult.java index 1294d08164..6fb6bb9c8d 100644 --- a/typespec-tests/src/main/java/com/cadl/longrunning/models/JobResult.java +++ b/typespec-tests/src/main/java/com/cadl/longrunning/models/JobResult.java @@ -162,46 +162,32 @@ public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { @Generated public static JobResult fromJson(JsonReader jsonReader) throws IOException { return jsonReader.readObject(reader -> { - String id = null; - JobStatus status = null; - OffsetDateTime createdDateTime = null; - OffsetDateTime expirationDateTime = null; - OffsetDateTime lastUpdateDateTime = null; - ResponseError error = null; - JobResultResult result = null; + JobResult deserializedJobResult = new JobResult(); while (reader.nextToken() != JsonToken.END_OBJECT) { String fieldName = reader.getFieldName(); reader.nextToken(); if ("id".equals(fieldName)) { - id = reader.getString(); + deserializedJobResult.id = reader.getString(); } else if ("status".equals(fieldName)) { - status = JobStatus.fromString(reader.getString()); + deserializedJobResult.status = JobStatus.fromString(reader.getString()); } else if ("createdDateTime".equals(fieldName)) { - createdDateTime + deserializedJobResult.createdDateTime = reader.getNullable(nonNullReader -> OffsetDateTime.parse(nonNullReader.getString())); } else if ("expirationDateTime".equals(fieldName)) { - expirationDateTime + deserializedJobResult.expirationDateTime = reader.getNullable(nonNullReader -> OffsetDateTime.parse(nonNullReader.getString())); } else if ("lastUpdateDateTime".equals(fieldName)) { - lastUpdateDateTime + deserializedJobResult.lastUpdateDateTime = reader.getNullable(nonNullReader -> OffsetDateTime.parse(nonNullReader.getString())); } else if ("error".equals(fieldName)) { - error = ResponseError.fromJson(reader); + deserializedJobResult.error = ResponseError.fromJson(reader); } else if ("result".equals(fieldName)) { - result = JobResultResult.fromJson(reader); + deserializedJobResult.result = JobResultResult.fromJson(reader); } else { reader.skipChildren(); } } - JobResult deserializedJobResult = new JobResult(); - deserializedJobResult.id = id; - deserializedJobResult.status = status; - deserializedJobResult.createdDateTime = createdDateTime; - deserializedJobResult.expirationDateTime = expirationDateTime; - deserializedJobResult.lastUpdateDateTime = lastUpdateDateTime; - deserializedJobResult.error = error; - deserializedJobResult.result = result; return deserializedJobResult; }); diff --git a/typespec-tests/src/main/java/com/cadl/multicontenttypes/models/Resource.java b/typespec-tests/src/main/java/com/cadl/multicontenttypes/models/Resource.java index c658bbc865..3a3afa1078 100644 --- a/typespec-tests/src/main/java/com/cadl/multicontenttypes/models/Resource.java +++ b/typespec-tests/src/main/java/com/cadl/multicontenttypes/models/Resource.java @@ -78,23 +78,19 @@ public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { @Generated public static Resource fromJson(JsonReader jsonReader) throws IOException { return jsonReader.readObject(reader -> { - String id = null; - String name = null; + Resource deserializedResource = new Resource(); while (reader.nextToken() != JsonToken.END_OBJECT) { String fieldName = reader.getFieldName(); reader.nextToken(); if ("id".equals(fieldName)) { - id = reader.getString(); + deserializedResource.id = reader.getString(); } else if ("name".equals(fieldName)) { - name = reader.getString(); + deserializedResource.name = reader.getString(); } else { reader.skipChildren(); } } - Resource deserializedResource = new Resource(); - deserializedResource.id = id; - deserializedResource.name = name; return deserializedResource; }); diff --git a/typespec-tests/src/main/java/com/cadl/patch/implementation/JsonMergePatchHelper.java b/typespec-tests/src/main/java/com/cadl/patch/implementation/JsonMergePatchHelper.java index 931275d2e4..0b02442171 100644 --- a/typespec-tests/src/main/java/com/cadl/patch/implementation/JsonMergePatchHelper.java +++ b/typespec-tests/src/main/java/com/cadl/patch/implementation/JsonMergePatchHelper.java @@ -16,6 +16,8 @@ public class JsonMergePatchHelper { public interface ResourceAccessor { Resource prepareModelForJsonMergePatch(Resource resource, boolean jsonMergePatchEnabled); + + boolean isJsonMergePatch(Resource resource); } public static void setResourceAccessor(ResourceAccessor accessor) { @@ -30,6 +32,8 @@ public static ResourceAccessor getResourceAccessor() { public interface InnerModelAccessor { InnerModel prepareModelForJsonMergePatch(InnerModel innerModel, boolean jsonMergePatchEnabled); + + boolean isJsonMergePatch(InnerModel innerModel); } public static void setInnerModelAccessor(InnerModelAccessor accessor) { @@ -44,6 +48,16 @@ public static InnerModelAccessor getInnerModelAccessor() { public interface FishAccessor { Fish prepareModelForJsonMergePatch(Fish fish, boolean jsonMergePatchEnabled); + + boolean isJsonMergePatch(Fish fish); + + void setId(Fish fish, String id); + + void setName(Fish fish, String name); + + void setAge(Fish fish, int age); + + void setColor(Fish fish, String color); } public static void setFishAccessor(FishAccessor accessor) { diff --git a/typespec-tests/src/main/java/com/cadl/patch/models/Fish.java b/typespec-tests/src/main/java/com/cadl/patch/models/Fish.java index de5467ae1b..dfe9f9f771 100644 --- a/typespec-tests/src/main/java/com/cadl/patch/models/Fish.java +++ b/typespec-tests/src/main/java/com/cadl/patch/models/Fish.java @@ -24,39 +24,31 @@ public class Fish implements JsonSerializable { * The kind property. */ @Generated - String kind; + private String kind; /* * The id property. */ @Generated - String id; + private String id; /* * The name property. */ @Generated - String name; + private String name; /* * The age property. */ @Generated - int age; + private int age; /* * The color property. */ @Generated - String color; - - @Generated - private boolean jsonMergePatch; - - @Generated - boolean isJsonMergePatch() { - return this.jsonMergePatch; - } + private String color; /** * Stores updated model property, the value is property name, not serialized name. @@ -64,15 +56,46 @@ boolean isJsonMergePatch() { @Generated private final Set updatedProperties = new HashSet<>(); + @Generated + private boolean jsonMergePatch; + @Generated private void serializeAsJsonMergePatch(boolean jsonMergePatch) { this.jsonMergePatch = jsonMergePatch; } static { - JsonMergePatchHelper.setFishAccessor((model, jsonMergePatchEnabled) -> { - model.serializeAsJsonMergePatch(jsonMergePatchEnabled); - return model; + JsonMergePatchHelper.setFishAccessor(new JsonMergePatchHelper.FishAccessor() { + @Override + public Fish prepareModelForJsonMergePatch(Fish model, boolean jsonMergePatchEnabled) { + model.serializeAsJsonMergePatch(jsonMergePatchEnabled); + return model; + } + + @Override + public boolean isJsonMergePatch(Fish model) { + return model.jsonMergePatch; + } + + @Override + public void setId(Fish model, String id) { + model.id = id; + } + + @Override + public void setName(Fish model, String name) { + model.name = name; + } + + @Override + public void setAge(Fish model, int age) { + model.age = age; + } + + @Override + public void setColor(Fish model, String color) { + model.color = color; + } }); } @@ -194,7 +217,7 @@ public Fish setColor(String color) { @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (isJsonMergePatch()) { + if (jsonMergePatch) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); @@ -253,7 +276,9 @@ public static Fish fromJson(JsonReader jsonReader) throws IOException { } // Use the discriminator value to determine which subtype should be deserialized. if ("shark".equals(discriminatorValue)) { - return Shark.fromJson(readerToUse.reset()); + return Shark.fromJsonKnownDiscriminator(readerToUse.reset()); + } else if ("saw".equals(discriminatorValue)) { + return SawShark.fromJson(readerToUse.reset()); } else if ("salmon".equals(discriminatorValue)) { return Salmon.fromJson(readerToUse.reset()); } else { @@ -266,35 +291,25 @@ public static Fish fromJson(JsonReader jsonReader) throws IOException { @Generated static Fish fromJsonKnownDiscriminator(JsonReader jsonReader) throws IOException { return jsonReader.readObject(reader -> { - String id = null; - String name = null; - String kind = null; - int age = 0; - String color = null; + Fish deserializedFish = new Fish(); while (reader.nextToken() != JsonToken.END_OBJECT) { String fieldName = reader.getFieldName(); reader.nextToken(); if ("id".equals(fieldName)) { - id = reader.getString(); + deserializedFish.id = reader.getString(); } else if ("name".equals(fieldName)) { - name = reader.getString(); + deserializedFish.name = reader.getString(); } else if ("kind".equals(fieldName)) { - kind = reader.getString(); + deserializedFish.kind = reader.getString(); } else if ("age".equals(fieldName)) { - age = reader.getInt(); + deserializedFish.age = reader.getInt(); } else if ("color".equals(fieldName)) { - color = reader.getString(); + deserializedFish.color = reader.getString(); } else { reader.skipChildren(); } } - Fish deserializedFish = new Fish(); - deserializedFish.id = id; - deserializedFish.name = name; - deserializedFish.kind = kind; - deserializedFish.age = age; - deserializedFish.color = color; return deserializedFish; }); diff --git a/typespec-tests/src/main/java/com/cadl/patch/models/InnerModel.java b/typespec-tests/src/main/java/com/cadl/patch/models/InnerModel.java index 66c0a2eba1..0be134f8dc 100644 --- a/typespec-tests/src/main/java/com/cadl/patch/models/InnerModel.java +++ b/typespec-tests/src/main/java/com/cadl/patch/models/InnerModel.java @@ -32,29 +32,32 @@ public final class InnerModel implements JsonSerializable { @Generated private String description; - @Generated - private boolean jsonMergePatch; - - @Generated - boolean isJsonMergePatch() { - return this.jsonMergePatch; - } - /** * Stores updated model property, the value is property name, not serialized name. */ @Generated private final Set updatedProperties = new HashSet<>(); + @Generated + private boolean jsonMergePatch; + @Generated private void serializeAsJsonMergePatch(boolean jsonMergePatch) { this.jsonMergePatch = jsonMergePatch; } static { - JsonMergePatchHelper.setInnerModelAccessor((model, jsonMergePatchEnabled) -> { - model.serializeAsJsonMergePatch(jsonMergePatchEnabled); - return model; + JsonMergePatchHelper.setInnerModelAccessor(new JsonMergePatchHelper.InnerModelAccessor() { + @Override + public InnerModel prepareModelForJsonMergePatch(InnerModel model, boolean jsonMergePatchEnabled) { + model.serializeAsJsonMergePatch(jsonMergePatchEnabled); + return model; + } + + @Override + public boolean isJsonMergePatch(InnerModel model) { + return model.jsonMergePatch; + } }); } @@ -118,7 +121,7 @@ public InnerModel setDescription(String description) { @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (isJsonMergePatch()) { + if (jsonMergePatch) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); diff --git a/typespec-tests/src/main/java/com/cadl/patch/models/Resource.java b/typespec-tests/src/main/java/com/cadl/patch/models/Resource.java index 2e5cd231e3..0255285d6a 100644 --- a/typespec-tests/src/main/java/com/cadl/patch/models/Resource.java +++ b/typespec-tests/src/main/java/com/cadl/patch/models/Resource.java @@ -82,29 +82,32 @@ public final class Resource implements JsonSerializable { @Generated private Fish fish; - @Generated - private boolean jsonMergePatch; - - @Generated - boolean isJsonMergePatch() { - return this.jsonMergePatch; - } - /** * Stores updated model property, the value is property name, not serialized name. */ @Generated private final Set updatedProperties = new HashSet<>(); + @Generated + private boolean jsonMergePatch; + @Generated private void serializeAsJsonMergePatch(boolean jsonMergePatch) { this.jsonMergePatch = jsonMergePatch; } static { - JsonMergePatchHelper.setResourceAccessor((model, jsonMergePatchEnabled) -> { - model.serializeAsJsonMergePatch(jsonMergePatchEnabled); - return model; + JsonMergePatchHelper.setResourceAccessor(new JsonMergePatchHelper.ResourceAccessor() { + @Override + public Resource prepareModelForJsonMergePatch(Resource model, boolean jsonMergePatchEnabled) { + model.serializeAsJsonMergePatch(jsonMergePatchEnabled); + return model; + } + + @Override + public boolean isJsonMergePatch(Resource model) { + return model.jsonMergePatch; + } }); } @@ -326,7 +329,7 @@ public Resource setFish(Fish fish) { @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (isJsonMergePatch()) { + if (jsonMergePatch) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); @@ -430,55 +433,37 @@ private JsonWriter toJsonMergePatch(JsonWriter jsonWriter) throws IOException { @Generated public static Resource fromJson(JsonReader jsonReader) throws IOException { return jsonReader.readObject(reader -> { - String id = null; - String name = null; - String description = null; - Map map = null; - Long longValue = null; - Integer intValue = null; - ResourceEnumValue enumValue = null; - InnerModel innerModelProperty = null; - List array = null; - Fish fish = null; + Resource deserializedResource = new Resource(); while (reader.nextToken() != JsonToken.END_OBJECT) { String fieldName = reader.getFieldName(); reader.nextToken(); if ("id".equals(fieldName)) { - id = reader.getString(); + deserializedResource.id = reader.getString(); } else if ("name".equals(fieldName)) { - name = reader.getString(); + deserializedResource.name = reader.getString(); } else if ("description".equals(fieldName)) { - description = reader.getString(); + deserializedResource.description = reader.getString(); } else if ("map".equals(fieldName)) { - map = reader.readMap(reader1 -> InnerModel.fromJson(reader1)); + Map map = reader.readMap(reader1 -> InnerModel.fromJson(reader1)); + deserializedResource.map = map; } else if ("longValue".equals(fieldName)) { - longValue = reader.getNullable(JsonReader::getLong); + deserializedResource.longValue = reader.getNullable(JsonReader::getLong); } else if ("intValue".equals(fieldName)) { - intValue = reader.getNullable(JsonReader::getInt); + deserializedResource.intValue = reader.getNullable(JsonReader::getInt); } else if ("enumValue".equals(fieldName)) { - enumValue = ResourceEnumValue.fromString(reader.getString()); + deserializedResource.enumValue = ResourceEnumValue.fromString(reader.getString()); } else if ("wireNameForInnerModelProperty".equals(fieldName)) { - innerModelProperty = InnerModel.fromJson(reader); + deserializedResource.innerModelProperty = InnerModel.fromJson(reader); } else if ("array".equals(fieldName)) { - array = reader.readArray(reader1 -> InnerModel.fromJson(reader1)); + List array = reader.readArray(reader1 -> InnerModel.fromJson(reader1)); + deserializedResource.array = array; } else if ("fish".equals(fieldName)) { - fish = Fish.fromJson(reader); + deserializedResource.fish = Fish.fromJson(reader); } else { reader.skipChildren(); } } - Resource deserializedResource = new Resource(); - deserializedResource.id = id; - deserializedResource.name = name; - deserializedResource.description = description; - deserializedResource.map = map; - deserializedResource.longValue = longValue; - deserializedResource.intValue = intValue; - deserializedResource.enumValue = enumValue; - deserializedResource.innerModelProperty = innerModelProperty; - deserializedResource.array = array; - deserializedResource.fish = fish; return deserializedResource; }); diff --git a/typespec-tests/src/main/java/com/cadl/patch/models/Salmon.java b/typespec-tests/src/main/java/com/cadl/patch/models/Salmon.java index 1e0e982670..04e7386224 100644 --- a/typespec-tests/src/main/java/com/cadl/patch/models/Salmon.java +++ b/typespec-tests/src/main/java/com/cadl/patch/models/Salmon.java @@ -168,7 +168,7 @@ public Salmon setColor(String color) { @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (isJsonMergePatch()) { + if (JsonMergePatchHelper.getFishAccessor().isJsonMergePatch(this)) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); @@ -246,47 +246,33 @@ private JsonWriter toJsonMergePatch(JsonWriter jsonWriter) throws IOException { @Generated public static Salmon fromJson(JsonReader jsonReader) throws IOException { return jsonReader.readObject(reader -> { - String id = null; - String name = null; - int age = 0; - String color = null; - String kind = "salmon"; - List friends = null; - Map hate = null; - Fish partner = null; + Salmon deserializedSalmon = new Salmon(); while (reader.nextToken() != JsonToken.END_OBJECT) { String fieldName = reader.getFieldName(); reader.nextToken(); if ("id".equals(fieldName)) { - id = reader.getString(); + JsonMergePatchHelper.getFishAccessor().setId(deserializedSalmon, reader.getString()); } else if ("name".equals(fieldName)) { - name = reader.getString(); + JsonMergePatchHelper.getFishAccessor().setName(deserializedSalmon, reader.getString()); } else if ("age".equals(fieldName)) { - age = reader.getInt(); + JsonMergePatchHelper.getFishAccessor().setAge(deserializedSalmon, reader.getInt()); } else if ("color".equals(fieldName)) { - color = reader.getString(); + JsonMergePatchHelper.getFishAccessor().setColor(deserializedSalmon, reader.getString()); } else if ("kind".equals(fieldName)) { - kind = reader.getString(); + deserializedSalmon.kind = reader.getString(); } else if ("friends".equals(fieldName)) { - friends = reader.readArray(reader1 -> Fish.fromJson(reader1)); + List friends = reader.readArray(reader1 -> Fish.fromJson(reader1)); + deserializedSalmon.friends = friends; } else if ("hate".equals(fieldName)) { - hate = reader.readMap(reader1 -> Fish.fromJson(reader1)); + Map hate = reader.readMap(reader1 -> Fish.fromJson(reader1)); + deserializedSalmon.hate = hate; } else if ("partner".equals(fieldName)) { - partner = Fish.fromJson(reader); + deserializedSalmon.partner = Fish.fromJson(reader); } else { reader.skipChildren(); } } - Salmon deserializedSalmon = new Salmon(); - deserializedSalmon.id = id; - deserializedSalmon.name = name; - deserializedSalmon.age = age; - deserializedSalmon.color = color; - deserializedSalmon.kind = kind; - deserializedSalmon.friends = friends; - deserializedSalmon.hate = hate; - deserializedSalmon.partner = partner; return deserializedSalmon; }); diff --git a/typespec-tests/src/main/java/com/cadl/patch/models/SawShark.java b/typespec-tests/src/main/java/com/cadl/patch/models/SawShark.java new file mode 100644 index 0000000000..5d9959e200 --- /dev/null +++ b/typespec-tests/src/main/java/com/cadl/patch/models/SawShark.java @@ -0,0 +1,148 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// Code generated by Microsoft (R) TypeSpec Code Generator. + +package com.cadl.patch.models; + +import com.azure.core.annotation.Fluent; +import com.azure.core.annotation.Generated; +import com.azure.json.JsonReader; +import com.azure.json.JsonToken; +import com.azure.json.JsonWriter; +import com.cadl.patch.implementation.JsonMergePatchHelper; +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; + +/** + * The third level model SawShark in polymorphic multiple levels inheritance. + */ +@Fluent +public final class SawShark extends Shark { + /* + * The sharktype property. + */ + @Generated + private String sharktype = "saw"; + + /** + * Stores updated model property, the value is property name, not serialized name. + */ + @Generated + private final Set updatedProperties = new HashSet<>(); + + /** + * Creates an instance of SawShark class. + */ + @Generated + public SawShark() { + this.updatedProperties.add("sharktype"); + } + + /** + * Get the sharktype property: The sharktype property. + * + * @return the sharktype value. + */ + @Generated + @Override + public String getSharktype() { + return this.sharktype; + } + + /** + * {@inheritDoc} + */ + @Generated + @Override + public SawShark setAge(int age) { + super.setAge(age); + this.updatedProperties.add("age"); + return this; + } + + /** + * {@inheritDoc} + */ + @Generated + @Override + public SawShark setColor(String color) { + super.setColor(color); + this.updatedProperties.add("color"); + return this; + } + + /** + * {@inheritDoc} + */ + @Generated + @Override + public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { + if (JsonMergePatchHelper.getFishAccessor().isJsonMergePatch(this)) { + return toJsonMergePatch(jsonWriter); + } else { + jsonWriter.writeStartObject(); + jsonWriter.writeIntField("age", getAge()); + jsonWriter.writeStringField("color", getColor()); + jsonWriter.writeStringField("sharktype", this.sharktype); + return jsonWriter.writeEndObject(); + } + } + + @Generated + private JsonWriter toJsonMergePatch(JsonWriter jsonWriter) throws IOException { + jsonWriter.writeStartObject(); + jsonWriter.writeIntField("age", getAge()); + if (updatedProperties.contains("color")) { + if (getColor() == null) { + jsonWriter.writeNullField("color"); + } else { + jsonWriter.writeStringField("color", getColor()); + } + } + if (updatedProperties.contains("sharktype")) { + if (this.sharktype == null) { + jsonWriter.writeNullField("sharktype"); + } else { + jsonWriter.writeStringField("sharktype", this.sharktype); + } + } + return jsonWriter.writeEndObject(); + } + + /** + * Reads an instance of SawShark from the JsonReader. + * + * @param jsonReader The JsonReader being read. + * @return An instance of SawShark if the JsonReader was pointing to an instance of it, or null if it was pointing + * to JSON null. + * @throws IllegalStateException If the deserialized JSON object was missing any required properties. + * @throws IOException If an error occurs while reading the SawShark. + */ + @Generated + public static SawShark fromJson(JsonReader jsonReader) throws IOException { + return jsonReader.readObject(reader -> { + SawShark deserializedSawShark = new SawShark(); + while (reader.nextToken() != JsonToken.END_OBJECT) { + String fieldName = reader.getFieldName(); + reader.nextToken(); + + if ("id".equals(fieldName)) { + JsonMergePatchHelper.getFishAccessor().setId(deserializedSawShark, reader.getString()); + } else if ("name".equals(fieldName)) { + JsonMergePatchHelper.getFishAccessor().setName(deserializedSawShark, reader.getString()); + } else if ("age".equals(fieldName)) { + JsonMergePatchHelper.getFishAccessor().setAge(deserializedSawShark, reader.getInt()); + } else if ("color".equals(fieldName)) { + JsonMergePatchHelper.getFishAccessor().setColor(deserializedSawShark, reader.getString()); + } else if ("sharktype".equals(fieldName)) { + deserializedSawShark.sharktype = reader.getString(); + } else { + reader.skipChildren(); + } + } + + return deserializedSawShark; + }); + } +} diff --git a/typespec-tests/src/main/java/com/cadl/patch/models/Shark.java b/typespec-tests/src/main/java/com/cadl/patch/models/Shark.java index 47d02d58a6..a150d13272 100644 --- a/typespec-tests/src/main/java/com/cadl/patch/models/Shark.java +++ b/typespec-tests/src/main/java/com/cadl/patch/models/Shark.java @@ -9,6 +9,7 @@ import com.azure.json.JsonReader; import com.azure.json.JsonToken; import com.azure.json.JsonWriter; +import com.cadl.patch.implementation.JsonMergePatchHelper; import java.io.IOException; import java.util.HashSet; import java.util.Set; @@ -17,12 +18,12 @@ * The second level model in polymorphic multiple levels inheritance and it defines a new discriminator. */ @Fluent -public final class Shark extends Fish { +public class Shark extends Fish { /* - * The kind property. + * The sharktype property. */ @Generated - private String kind = "shark"; + private String sharktype = "shark"; /** * Stores updated model property, the value is property name, not serialized name. @@ -35,18 +36,18 @@ public final class Shark extends Fish { */ @Generated public Shark() { - this.updatedProperties.add("kind"); + this.sharktype = "shark"; + this.updatedProperties.add("sharktype"); } /** - * Get the kind property: The kind property. + * Get the sharktype property: The sharktype property. * - * @return the kind value. + * @return the sharktype value. */ @Generated - @Override - public String getKind() { - return this.kind; + public String getSharktype() { + return this.sharktype; } /** @@ -77,13 +78,13 @@ public Shark setColor(String color) { @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (isJsonMergePatch()) { + if (JsonMergePatchHelper.getFishAccessor().isJsonMergePatch(this)) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); jsonWriter.writeIntField("age", getAge()); jsonWriter.writeStringField("color", getColor()); - jsonWriter.writeStringField("kind", this.kind); + jsonWriter.writeStringField("sharktype", this.sharktype); return jsonWriter.writeEndObject(); } } @@ -99,11 +100,11 @@ private JsonWriter toJsonMergePatch(JsonWriter jsonWriter) throws IOException { jsonWriter.writeStringField("color", getColor()); } } - if (updatedProperties.contains("kind")) { - if (this.kind == null) { - jsonWriter.writeNullField("kind"); + if (updatedProperties.contains("sharktype")) { + if (this.sharktype == null) { + jsonWriter.writeNullField("sharktype"); } else { - jsonWriter.writeStringField("kind", this.kind); + jsonWriter.writeStringField("sharktype", this.sharktype); } } return jsonWriter.writeEndObject(); @@ -121,35 +122,51 @@ private JsonWriter toJsonMergePatch(JsonWriter jsonWriter) throws IOException { @Generated public static Shark fromJson(JsonReader jsonReader) throws IOException { return jsonReader.readObject(reader -> { - String id = null; - String name = null; - int age = 0; - String color = null; - String kind = "shark"; + String discriminatorValue = null; + try (JsonReader readerToUse = reader.bufferObject()) { + readerToUse.nextToken(); // Prepare for reading + while (readerToUse.nextToken() != JsonToken.END_OBJECT) { + String fieldName = readerToUse.getFieldName(); + readerToUse.nextToken(); + if ("sharktype".equals(fieldName)) { + discriminatorValue = readerToUse.getString(); + break; + } else { + readerToUse.skipChildren(); + } + } + // Use the discriminator value to determine which subtype should be deserialized. + if ("saw".equals(discriminatorValue)) { + return SawShark.fromJson(readerToUse.reset()); + } else { + return fromJsonKnownDiscriminator(readerToUse.reset()); + } + } + }); + } + + @Generated + static Shark fromJsonKnownDiscriminator(JsonReader jsonReader) throws IOException { + return jsonReader.readObject(reader -> { + Shark deserializedShark = new Shark(); while (reader.nextToken() != JsonToken.END_OBJECT) { String fieldName = reader.getFieldName(); reader.nextToken(); if ("id".equals(fieldName)) { - id = reader.getString(); + JsonMergePatchHelper.getFishAccessor().setId(deserializedShark, reader.getString()); } else if ("name".equals(fieldName)) { - name = reader.getString(); + JsonMergePatchHelper.getFishAccessor().setName(deserializedShark, reader.getString()); } else if ("age".equals(fieldName)) { - age = reader.getInt(); + JsonMergePatchHelper.getFishAccessor().setAge(deserializedShark, reader.getInt()); } else if ("color".equals(fieldName)) { - color = reader.getString(); - } else if ("kind".equals(fieldName)) { - kind = reader.getString(); + JsonMergePatchHelper.getFishAccessor().setColor(deserializedShark, reader.getString()); + } else if ("sharktype".equals(fieldName)) { + deserializedShark.sharktype = reader.getString(); } else { reader.skipChildren(); } } - Shark deserializedShark = new Shark(); - deserializedShark.id = id; - deserializedShark.name = name; - deserializedShark.age = age; - deserializedShark.color = color; - deserializedShark.kind = kind; return deserializedShark; }); diff --git a/typespec-tests/src/main/java/com/cadl/specialheaders/implementation/JsonMergePatchHelper.java b/typespec-tests/src/main/java/com/cadl/specialheaders/implementation/JsonMergePatchHelper.java index 0dc7db0585..6498907160 100644 --- a/typespec-tests/src/main/java/com/cadl/specialheaders/implementation/JsonMergePatchHelper.java +++ b/typespec-tests/src/main/java/com/cadl/specialheaders/implementation/JsonMergePatchHelper.java @@ -14,6 +14,8 @@ public class JsonMergePatchHelper { public interface ResourceAccessor { Resource prepareModelForJsonMergePatch(Resource resource, boolean jsonMergePatchEnabled); + + boolean isJsonMergePatch(Resource resource); } public static void setResourceAccessor(ResourceAccessor accessor) { diff --git a/typespec-tests/src/main/java/com/cadl/specialheaders/models/Resource.java b/typespec-tests/src/main/java/com/cadl/specialheaders/models/Resource.java index 2c8cd0cfcb..ed957f974e 100644 --- a/typespec-tests/src/main/java/com/cadl/specialheaders/models/Resource.java +++ b/typespec-tests/src/main/java/com/cadl/specialheaders/models/Resource.java @@ -44,29 +44,32 @@ public final class Resource implements JsonSerializable { @Generated private String type; - @Generated - private boolean jsonMergePatch; - - @Generated - boolean isJsonMergePatch() { - return this.jsonMergePatch; - } - /** * Stores updated model property, the value is property name, not serialized name. */ @Generated private final Set updatedProperties = new HashSet<>(); + @Generated + private boolean jsonMergePatch; + @Generated private void serializeAsJsonMergePatch(boolean jsonMergePatch) { this.jsonMergePatch = jsonMergePatch; } static { - JsonMergePatchHelper.setResourceAccessor((model, jsonMergePatchEnabled) -> { - model.serializeAsJsonMergePatch(jsonMergePatchEnabled); - return model; + JsonMergePatchHelper.setResourceAccessor(new JsonMergePatchHelper.ResourceAccessor() { + @Override + public Resource prepareModelForJsonMergePatch(Resource model, boolean jsonMergePatchEnabled) { + model.serializeAsJsonMergePatch(jsonMergePatchEnabled); + return model; + } + + @Override + public boolean isJsonMergePatch(Resource model) { + return model.jsonMergePatch; + } }); } @@ -150,7 +153,7 @@ public Resource setType(String type) { @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (isJsonMergePatch()) { + if (jsonMergePatch) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); @@ -192,31 +195,23 @@ private JsonWriter toJsonMergePatch(JsonWriter jsonWriter) throws IOException { @Generated public static Resource fromJson(JsonReader jsonReader) throws IOException { return jsonReader.readObject(reader -> { - String id = null; - String name = null; - String description = null; - String type = null; + Resource deserializedResource = new Resource(); while (reader.nextToken() != JsonToken.END_OBJECT) { String fieldName = reader.getFieldName(); reader.nextToken(); if ("id".equals(fieldName)) { - id = reader.getString(); + deserializedResource.id = reader.getString(); } else if ("name".equals(fieldName)) { - name = reader.getString(); + deserializedResource.name = reader.getString(); } else if ("description".equals(fieldName)) { - description = reader.getString(); + deserializedResource.description = reader.getString(); } else if ("type".equals(fieldName)) { - type = reader.getString(); + deserializedResource.type = reader.getString(); } else { reader.skipChildren(); } } - Resource deserializedResource = new Resource(); - deserializedResource.id = id; - deserializedResource.name = name; - deserializedResource.description = description; - deserializedResource.type = type; return deserializedResource; }); diff --git a/typespec-tests/src/main/java/com/payload/jsonmergepatch/implementation/JsonMergePatchHelper.java b/typespec-tests/src/main/java/com/payload/jsonmergepatch/implementation/JsonMergePatchHelper.java index c198c9ea4f..303c8b6b56 100644 --- a/typespec-tests/src/main/java/com/payload/jsonmergepatch/implementation/JsonMergePatchHelper.java +++ b/typespec-tests/src/main/java/com/payload/jsonmergepatch/implementation/JsonMergePatchHelper.java @@ -15,6 +15,8 @@ public class JsonMergePatchHelper { public interface InnerModelAccessor { InnerModel prepareModelForJsonMergePatch(InnerModel innerModel, boolean jsonMergePatchEnabled); + + boolean isJsonMergePatch(InnerModel innerModel); } public static void setInnerModelAccessor(InnerModelAccessor accessor) { @@ -29,6 +31,8 @@ public static InnerModelAccessor getInnerModelAccessor() { public interface ResourcePatchAccessor { ResourcePatch prepareModelForJsonMergePatch(ResourcePatch resourcePatch, boolean jsonMergePatchEnabled); + + boolean isJsonMergePatch(ResourcePatch resourcePatch); } public static void setResourcePatchAccessor(ResourcePatchAccessor accessor) { diff --git a/typespec-tests/src/main/java/com/payload/jsonmergepatch/models/InnerModel.java b/typespec-tests/src/main/java/com/payload/jsonmergepatch/models/InnerModel.java index bc5a6cb6b8..b21ef54609 100644 --- a/typespec-tests/src/main/java/com/payload/jsonmergepatch/models/InnerModel.java +++ b/typespec-tests/src/main/java/com/payload/jsonmergepatch/models/InnerModel.java @@ -32,29 +32,32 @@ public final class InnerModel implements JsonSerializable { @Generated private String description; - @Generated - private boolean jsonMergePatch; - - @Generated - boolean isJsonMergePatch() { - return this.jsonMergePatch; - } - /** * Stores updated model property, the value is property name, not serialized name. */ @Generated private final Set updatedProperties = new HashSet<>(); + @Generated + private boolean jsonMergePatch; + @Generated private void serializeAsJsonMergePatch(boolean jsonMergePatch) { this.jsonMergePatch = jsonMergePatch; } static { - JsonMergePatchHelper.setInnerModelAccessor((model, jsonMergePatchEnabled) -> { - model.serializeAsJsonMergePatch(jsonMergePatchEnabled); - return model; + JsonMergePatchHelper.setInnerModelAccessor(new JsonMergePatchHelper.InnerModelAccessor() { + @Override + public InnerModel prepareModelForJsonMergePatch(InnerModel model, boolean jsonMergePatchEnabled) { + model.serializeAsJsonMergePatch(jsonMergePatchEnabled); + return model; + } + + @Override + public boolean isJsonMergePatch(InnerModel model) { + return model.jsonMergePatch; + } }); } @@ -117,7 +120,7 @@ public InnerModel setDescription(String description) { @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (isJsonMergePatch()) { + if (jsonMergePatch) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); diff --git a/typespec-tests/src/main/java/com/payload/jsonmergepatch/models/ResourcePatch.java b/typespec-tests/src/main/java/com/payload/jsonmergepatch/models/ResourcePatch.java index fe0c4bb584..a55bd12eb5 100644 --- a/typespec-tests/src/main/java/com/payload/jsonmergepatch/models/ResourcePatch.java +++ b/typespec-tests/src/main/java/com/payload/jsonmergepatch/models/ResourcePatch.java @@ -64,29 +64,32 @@ public final class ResourcePatch implements JsonSerializable { @Generated private List intArray; - @Generated - private boolean jsonMergePatch; - - @Generated - boolean isJsonMergePatch() { - return this.jsonMergePatch; - } - /** * Stores updated model property, the value is property name, not serialized name. */ @Generated private final Set updatedProperties = new HashSet<>(); + @Generated + private boolean jsonMergePatch; + @Generated private void serializeAsJsonMergePatch(boolean jsonMergePatch) { this.jsonMergePatch = jsonMergePatch; } static { - JsonMergePatchHelper.setResourcePatchAccessor((model, jsonMergePatchEnabled) -> { - model.serializeAsJsonMergePatch(jsonMergePatchEnabled); - return model; + JsonMergePatchHelper.setResourcePatchAccessor(new JsonMergePatchHelper.ResourcePatchAccessor() { + @Override + public ResourcePatch prepareModelForJsonMergePatch(ResourcePatch model, boolean jsonMergePatchEnabled) { + model.serializeAsJsonMergePatch(jsonMergePatchEnabled); + return model; + } + + @Override + public boolean isJsonMergePatch(ResourcePatch model) { + return model.jsonMergePatch; + } }); } @@ -264,7 +267,7 @@ public ResourcePatch setIntArray(List intArray) { @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (isJsonMergePatch()) { + if (jsonMergePatch) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); diff --git a/typespec-tests/src/main/java/com/type/property/nullable/implementation/JsonMergePatchHelper.java b/typespec-tests/src/main/java/com/type/property/nullable/implementation/JsonMergePatchHelper.java index 5c89e6280d..94ec84db5d 100644 --- a/typespec-tests/src/main/java/com/type/property/nullable/implementation/JsonMergePatchHelper.java +++ b/typespec-tests/src/main/java/com/type/property/nullable/implementation/JsonMergePatchHelper.java @@ -20,6 +20,8 @@ public class JsonMergePatchHelper { public interface StringPropertyAccessor { StringProperty prepareModelForJsonMergePatch(StringProperty stringProperty, boolean jsonMergePatchEnabled); + + boolean isJsonMergePatch(StringProperty stringProperty); } public static void setStringPropertyAccessor(StringPropertyAccessor accessor) { @@ -34,6 +36,8 @@ public static StringPropertyAccessor getStringPropertyAccessor() { public interface BytesPropertyAccessor { BytesProperty prepareModelForJsonMergePatch(BytesProperty bytesProperty, boolean jsonMergePatchEnabled); + + boolean isJsonMergePatch(BytesProperty bytesProperty); } public static void setBytesPropertyAccessor(BytesPropertyAccessor accessor) { @@ -49,6 +53,8 @@ public static BytesPropertyAccessor getBytesPropertyAccessor() { public interface DatetimePropertyAccessor { DatetimeProperty prepareModelForJsonMergePatch(DatetimeProperty datetimeProperty, boolean jsonMergePatchEnabled); + + boolean isJsonMergePatch(DatetimeProperty datetimeProperty); } public static void setDatetimePropertyAccessor(DatetimePropertyAccessor accessor) { @@ -64,6 +70,8 @@ public static DatetimePropertyAccessor getDatetimePropertyAccessor() { public interface DurationPropertyAccessor { DurationProperty prepareModelForJsonMergePatch(DurationProperty durationProperty, boolean jsonMergePatchEnabled); + + boolean isJsonMergePatch(DurationProperty durationProperty); } public static void setDurationPropertyAccessor(DurationPropertyAccessor accessor) { @@ -79,6 +87,8 @@ public static DurationPropertyAccessor getDurationPropertyAccessor() { public interface CollectionsBytePropertyAccessor { CollectionsByteProperty prepareModelForJsonMergePatch(CollectionsByteProperty collectionsByteProperty, boolean jsonMergePatchEnabled); + + boolean isJsonMergePatch(CollectionsByteProperty collectionsByteProperty); } public static void setCollectionsBytePropertyAccessor(CollectionsBytePropertyAccessor accessor) { @@ -94,6 +104,8 @@ public static CollectionsBytePropertyAccessor getCollectionsBytePropertyAccessor public interface CollectionsModelPropertyAccessor { CollectionsModelProperty prepareModelForJsonMergePatch(CollectionsModelProperty collectionsModelProperty, boolean jsonMergePatchEnabled); + + boolean isJsonMergePatch(CollectionsModelProperty collectionsModelProperty); } public static void setCollectionsModelPropertyAccessor(CollectionsModelPropertyAccessor accessor) { @@ -108,6 +120,8 @@ public static CollectionsModelPropertyAccessor getCollectionsModelPropertyAccess public interface InnerModelAccessor { InnerModel prepareModelForJsonMergePatch(InnerModel innerModel, boolean jsonMergePatchEnabled); + + boolean isJsonMergePatch(InnerModel innerModel); } public static void setInnerModelAccessor(InnerModelAccessor accessor) { diff --git a/typespec-tests/src/main/java/com/type/property/nullable/models/BytesProperty.java b/typespec-tests/src/main/java/com/type/property/nullable/models/BytesProperty.java index c22c55ecb0..efcb62904c 100644 --- a/typespec-tests/src/main/java/com/type/property/nullable/models/BytesProperty.java +++ b/typespec-tests/src/main/java/com/type/property/nullable/models/BytesProperty.java @@ -33,29 +33,32 @@ public final class BytesProperty implements JsonSerializable { @Generated private byte[] nullableProperty; - @Generated - private boolean jsonMergePatch; - - @Generated - boolean isJsonMergePatch() { - return this.jsonMergePatch; - } - /** * Stores updated model property, the value is property name, not serialized name. */ @Generated private final Set updatedProperties = new HashSet<>(); + @Generated + private boolean jsonMergePatch; + @Generated private void serializeAsJsonMergePatch(boolean jsonMergePatch) { this.jsonMergePatch = jsonMergePatch; } static { - JsonMergePatchHelper.setBytesPropertyAccessor((model, jsonMergePatchEnabled) -> { - model.serializeAsJsonMergePatch(jsonMergePatchEnabled); - return model; + JsonMergePatchHelper.setBytesPropertyAccessor(new JsonMergePatchHelper.BytesPropertyAccessor() { + @Override + public BytesProperty prepareModelForJsonMergePatch(BytesProperty model, boolean jsonMergePatchEnabled) { + model.serializeAsJsonMergePatch(jsonMergePatchEnabled); + return model; + } + + @Override + public boolean isJsonMergePatch(BytesProperty model) { + return model.jsonMergePatch; + } }); } @@ -120,7 +123,7 @@ public BytesProperty setNullableProperty(byte[] nullableProperty) { @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (isJsonMergePatch()) { + if (jsonMergePatch) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); diff --git a/typespec-tests/src/main/java/com/type/property/nullable/models/CollectionsByteProperty.java b/typespec-tests/src/main/java/com/type/property/nullable/models/CollectionsByteProperty.java index 79c6051420..50f91335d2 100644 --- a/typespec-tests/src/main/java/com/type/property/nullable/models/CollectionsByteProperty.java +++ b/typespec-tests/src/main/java/com/type/property/nullable/models/CollectionsByteProperty.java @@ -33,30 +33,35 @@ public final class CollectionsByteProperty implements JsonSerializable nullableProperty; - @Generated - private boolean jsonMergePatch; - - @Generated - boolean isJsonMergePatch() { - return this.jsonMergePatch; - } - /** * Stores updated model property, the value is property name, not serialized name. */ @Generated private final Set updatedProperties = new HashSet<>(); + @Generated + private boolean jsonMergePatch; + @Generated private void serializeAsJsonMergePatch(boolean jsonMergePatch) { this.jsonMergePatch = jsonMergePatch; } static { - JsonMergePatchHelper.setCollectionsBytePropertyAccessor((model, jsonMergePatchEnabled) -> { - model.serializeAsJsonMergePatch(jsonMergePatchEnabled); - return model; - }); + JsonMergePatchHelper + .setCollectionsBytePropertyAccessor(new JsonMergePatchHelper.CollectionsBytePropertyAccessor() { + @Override + public CollectionsByteProperty prepareModelForJsonMergePatch(CollectionsByteProperty model, + boolean jsonMergePatchEnabled) { + model.serializeAsJsonMergePatch(jsonMergePatchEnabled); + return model; + } + + @Override + public boolean isJsonMergePatch(CollectionsByteProperty model) { + return model.jsonMergePatch; + } + }); } /** @@ -120,7 +125,7 @@ public CollectionsByteProperty setNullableProperty(List nullableProperty @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (isJsonMergePatch()) { + if (jsonMergePatch) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); diff --git a/typespec-tests/src/main/java/com/type/property/nullable/models/CollectionsModelProperty.java b/typespec-tests/src/main/java/com/type/property/nullable/models/CollectionsModelProperty.java index 9cc70ffbea..11e195750b 100644 --- a/typespec-tests/src/main/java/com/type/property/nullable/models/CollectionsModelProperty.java +++ b/typespec-tests/src/main/java/com/type/property/nullable/models/CollectionsModelProperty.java @@ -33,30 +33,35 @@ public final class CollectionsModelProperty implements JsonSerializable nullableProperty; - @Generated - private boolean jsonMergePatch; - - @Generated - boolean isJsonMergePatch() { - return this.jsonMergePatch; - } - /** * Stores updated model property, the value is property name, not serialized name. */ @Generated private final Set updatedProperties = new HashSet<>(); + @Generated + private boolean jsonMergePatch; + @Generated private void serializeAsJsonMergePatch(boolean jsonMergePatch) { this.jsonMergePatch = jsonMergePatch; } static { - JsonMergePatchHelper.setCollectionsModelPropertyAccessor((model, jsonMergePatchEnabled) -> { - model.serializeAsJsonMergePatch(jsonMergePatchEnabled); - return model; - }); + JsonMergePatchHelper + .setCollectionsModelPropertyAccessor(new JsonMergePatchHelper.CollectionsModelPropertyAccessor() { + @Override + public CollectionsModelProperty prepareModelForJsonMergePatch(CollectionsModelProperty model, + boolean jsonMergePatchEnabled) { + model.serializeAsJsonMergePatch(jsonMergePatchEnabled); + return model; + } + + @Override + public boolean isJsonMergePatch(CollectionsModelProperty model) { + return model.jsonMergePatch; + } + }); } /** @@ -120,7 +125,7 @@ public CollectionsModelProperty setNullableProperty(List nullablePro @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (isJsonMergePatch()) { + if (jsonMergePatch) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); diff --git a/typespec-tests/src/main/java/com/type/property/nullable/models/DatetimeProperty.java b/typespec-tests/src/main/java/com/type/property/nullable/models/DatetimeProperty.java index d0e5cf6f0a..6c181f0a50 100644 --- a/typespec-tests/src/main/java/com/type/property/nullable/models/DatetimeProperty.java +++ b/typespec-tests/src/main/java/com/type/property/nullable/models/DatetimeProperty.java @@ -34,29 +34,33 @@ public final class DatetimeProperty implements JsonSerializable updatedProperties = new HashSet<>(); + @Generated + private boolean jsonMergePatch; + @Generated private void serializeAsJsonMergePatch(boolean jsonMergePatch) { this.jsonMergePatch = jsonMergePatch; } static { - JsonMergePatchHelper.setDatetimePropertyAccessor((model, jsonMergePatchEnabled) -> { - model.serializeAsJsonMergePatch(jsonMergePatchEnabled); - return model; + JsonMergePatchHelper.setDatetimePropertyAccessor(new JsonMergePatchHelper.DatetimePropertyAccessor() { + @Override + public DatetimeProperty prepareModelForJsonMergePatch(DatetimeProperty model, + boolean jsonMergePatchEnabled) { + model.serializeAsJsonMergePatch(jsonMergePatchEnabled); + return model; + } + + @Override + public boolean isJsonMergePatch(DatetimeProperty model) { + return model.jsonMergePatch; + } }); } @@ -121,7 +125,7 @@ public DatetimeProperty setNullableProperty(OffsetDateTime nullableProperty) { @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (isJsonMergePatch()) { + if (jsonMergePatch) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); diff --git a/typespec-tests/src/main/java/com/type/property/nullable/models/DurationProperty.java b/typespec-tests/src/main/java/com/type/property/nullable/models/DurationProperty.java index 93755f72b8..b9750709d1 100644 --- a/typespec-tests/src/main/java/com/type/property/nullable/models/DurationProperty.java +++ b/typespec-tests/src/main/java/com/type/property/nullable/models/DurationProperty.java @@ -34,29 +34,33 @@ public final class DurationProperty implements JsonSerializable updatedProperties = new HashSet<>(); + @Generated + private boolean jsonMergePatch; + @Generated private void serializeAsJsonMergePatch(boolean jsonMergePatch) { this.jsonMergePatch = jsonMergePatch; } static { - JsonMergePatchHelper.setDurationPropertyAccessor((model, jsonMergePatchEnabled) -> { - model.serializeAsJsonMergePatch(jsonMergePatchEnabled); - return model; + JsonMergePatchHelper.setDurationPropertyAccessor(new JsonMergePatchHelper.DurationPropertyAccessor() { + @Override + public DurationProperty prepareModelForJsonMergePatch(DurationProperty model, + boolean jsonMergePatchEnabled) { + model.serializeAsJsonMergePatch(jsonMergePatchEnabled); + return model; + } + + @Override + public boolean isJsonMergePatch(DurationProperty model) { + return model.jsonMergePatch; + } }); } @@ -121,7 +125,7 @@ public DurationProperty setNullableProperty(Duration nullableProperty) { @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (isJsonMergePatch()) { + if (jsonMergePatch) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); diff --git a/typespec-tests/src/main/java/com/type/property/nullable/models/InnerModel.java b/typespec-tests/src/main/java/com/type/property/nullable/models/InnerModel.java index 49f6c882d6..18c53df607 100644 --- a/typespec-tests/src/main/java/com/type/property/nullable/models/InnerModel.java +++ b/typespec-tests/src/main/java/com/type/property/nullable/models/InnerModel.java @@ -26,29 +26,32 @@ public final class InnerModel implements JsonSerializable { @Generated private String property; - @Generated - private boolean jsonMergePatch; - - @Generated - boolean isJsonMergePatch() { - return this.jsonMergePatch; - } - /** * Stores updated model property, the value is property name, not serialized name. */ @Generated private final Set updatedProperties = new HashSet<>(); + @Generated + private boolean jsonMergePatch; + @Generated private void serializeAsJsonMergePatch(boolean jsonMergePatch) { this.jsonMergePatch = jsonMergePatch; } static { - JsonMergePatchHelper.setInnerModelAccessor((model, jsonMergePatchEnabled) -> { - model.serializeAsJsonMergePatch(jsonMergePatchEnabled); - return model; + JsonMergePatchHelper.setInnerModelAccessor(new JsonMergePatchHelper.InnerModelAccessor() { + @Override + public InnerModel prepareModelForJsonMergePatch(InnerModel model, boolean jsonMergePatchEnabled) { + model.serializeAsJsonMergePatch(jsonMergePatchEnabled); + return model; + } + + @Override + public boolean isJsonMergePatch(InnerModel model) { + return model.jsonMergePatch; + } }); } @@ -89,7 +92,7 @@ public InnerModel setProperty(String property) { @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (isJsonMergePatch()) { + if (jsonMergePatch) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); diff --git a/typespec-tests/src/main/java/com/type/property/nullable/models/StringProperty.java b/typespec-tests/src/main/java/com/type/property/nullable/models/StringProperty.java index fc4ec744e7..861c05f658 100644 --- a/typespec-tests/src/main/java/com/type/property/nullable/models/StringProperty.java +++ b/typespec-tests/src/main/java/com/type/property/nullable/models/StringProperty.java @@ -32,29 +32,32 @@ public final class StringProperty implements JsonSerializable { @Generated private String nullableProperty; - @Generated - private boolean jsonMergePatch; - - @Generated - boolean isJsonMergePatch() { - return this.jsonMergePatch; - } - /** * Stores updated model property, the value is property name, not serialized name. */ @Generated private final Set updatedProperties = new HashSet<>(); + @Generated + private boolean jsonMergePatch; + @Generated private void serializeAsJsonMergePatch(boolean jsonMergePatch) { this.jsonMergePatch = jsonMergePatch; } static { - JsonMergePatchHelper.setStringPropertyAccessor((model, jsonMergePatchEnabled) -> { - model.serializeAsJsonMergePatch(jsonMergePatchEnabled); - return model; + JsonMergePatchHelper.setStringPropertyAccessor(new JsonMergePatchHelper.StringPropertyAccessor() { + @Override + public StringProperty prepareModelForJsonMergePatch(StringProperty model, boolean jsonMergePatchEnabled) { + model.serializeAsJsonMergePatch(jsonMergePatchEnabled); + return model; + } + + @Override + public boolean isJsonMergePatch(StringProperty model) { + return model.jsonMergePatch; + } }); } @@ -119,7 +122,7 @@ public StringProperty setNullableProperty(String nullableProperty) { @Generated @Override public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { - if (isJsonMergePatch()) { + if (jsonMergePatch) { return toJsonMergePatch(jsonWriter); } else { jsonWriter.writeStartObject(); diff --git a/typespec-tests/src/main/java/com/type/property/valuetypes/models/BooleanLiteralProperty.java b/typespec-tests/src/main/java/com/type/property/valuetypes/models/BooleanLiteralProperty.java index 409be682db..e449fcb467 100644 --- a/typespec-tests/src/main/java/com/type/property/valuetypes/models/BooleanLiteralProperty.java +++ b/typespec-tests/src/main/java/com/type/property/valuetypes/models/BooleanLiteralProperty.java @@ -63,13 +63,15 @@ public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { @Generated public static BooleanLiteralProperty fromJson(JsonReader jsonReader) throws IOException { return jsonReader.readObject(reader -> { + BooleanLiteralProperty deserializedBooleanLiteralProperty = new BooleanLiteralProperty(); while (reader.nextToken() != JsonToken.END_OBJECT) { String fieldName = reader.getFieldName(); reader.nextToken(); reader.skipChildren(); } - return new BooleanLiteralProperty(); + + return deserializedBooleanLiteralProperty; }); } } diff --git a/typespec-tests/src/main/java/com/type/property/valuetypes/models/FloatLiteralProperty.java b/typespec-tests/src/main/java/com/type/property/valuetypes/models/FloatLiteralProperty.java index 118e0fef35..5d5b3f406f 100644 --- a/typespec-tests/src/main/java/com/type/property/valuetypes/models/FloatLiteralProperty.java +++ b/typespec-tests/src/main/java/com/type/property/valuetypes/models/FloatLiteralProperty.java @@ -63,13 +63,15 @@ public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { @Generated public static FloatLiteralProperty fromJson(JsonReader jsonReader) throws IOException { return jsonReader.readObject(reader -> { + FloatLiteralProperty deserializedFloatLiteralProperty = new FloatLiteralProperty(); while (reader.nextToken() != JsonToken.END_OBJECT) { String fieldName = reader.getFieldName(); reader.nextToken(); reader.skipChildren(); } - return new FloatLiteralProperty(); + + return deserializedFloatLiteralProperty; }); } } diff --git a/typespec-tests/src/main/java/com/type/property/valuetypes/models/IntLiteralProperty.java b/typespec-tests/src/main/java/com/type/property/valuetypes/models/IntLiteralProperty.java index 50ced0ae1e..f48bdbb44b 100644 --- a/typespec-tests/src/main/java/com/type/property/valuetypes/models/IntLiteralProperty.java +++ b/typespec-tests/src/main/java/com/type/property/valuetypes/models/IntLiteralProperty.java @@ -63,13 +63,15 @@ public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { @Generated public static IntLiteralProperty fromJson(JsonReader jsonReader) throws IOException { return jsonReader.readObject(reader -> { + IntLiteralProperty deserializedIntLiteralProperty = new IntLiteralProperty(); while (reader.nextToken() != JsonToken.END_OBJECT) { String fieldName = reader.getFieldName(); reader.nextToken(); reader.skipChildren(); } - return new IntLiteralProperty(); + + return deserializedIntLiteralProperty; }); } } diff --git a/typespec-tests/src/main/java/com/type/property/valuetypes/models/StringLiteralProperty.java b/typespec-tests/src/main/java/com/type/property/valuetypes/models/StringLiteralProperty.java index 65fdea8f5a..b355792892 100644 --- a/typespec-tests/src/main/java/com/type/property/valuetypes/models/StringLiteralProperty.java +++ b/typespec-tests/src/main/java/com/type/property/valuetypes/models/StringLiteralProperty.java @@ -63,13 +63,15 @@ public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { @Generated public static StringLiteralProperty fromJson(JsonReader jsonReader) throws IOException { return jsonReader.readObject(reader -> { + StringLiteralProperty deserializedStringLiteralProperty = new StringLiteralProperty(); while (reader.nextToken() != JsonToken.END_OBJECT) { String fieldName = reader.getFieldName(); reader.nextToken(); reader.skipChildren(); } - return new StringLiteralProperty(); + + return deserializedStringLiteralProperty; }); } } diff --git a/typespec-tests/src/main/java/com/type/property/valuetypes/models/UnionEnumValueProperty.java b/typespec-tests/src/main/java/com/type/property/valuetypes/models/UnionEnumValueProperty.java index 59aed145d5..cd0bfb3203 100644 --- a/typespec-tests/src/main/java/com/type/property/valuetypes/models/UnionEnumValueProperty.java +++ b/typespec-tests/src/main/java/com/type/property/valuetypes/models/UnionEnumValueProperty.java @@ -63,13 +63,15 @@ public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { @Generated public static UnionEnumValueProperty fromJson(JsonReader jsonReader) throws IOException { return jsonReader.readObject(reader -> { + UnionEnumValueProperty deserializedUnionEnumValueProperty = new UnionEnumValueProperty(); while (reader.nextToken() != JsonToken.END_OBJECT) { String fieldName = reader.getFieldName(); reader.nextToken(); reader.skipChildren(); } - return new UnionEnumValueProperty(); + + return deserializedUnionEnumValueProperty; }); } } diff --git a/typespec-tests/tsp/patch.tsp b/typespec-tests/tsp/patch.tsp index 340aff2f9a..ccded004a4 100644 --- a/typespec-tests/tsp/patch.tsp +++ b/typespec-tests/tsp/patch.tsp @@ -58,8 +58,15 @@ model Fish { } @doc("The second level model in polymorphic multiple levels inheritance and it defines a new discriminator.") +@discriminator("sharktype") model Shark extends Fish { kind: "shark"; + sharktype: string; +} + +@doc("The third level model SawShark in polymorphic multiple levels inheritance.") +model SawShark extends Shark { + sharktype: "saw"; } @doc("The second level model in polymorphic multiple levels inheritance which contains references to other polymorphic instances.") diff --git a/vanilla-tests/src/main/java/fixtures/inheritance/passdiscriminator/models/MetricAlertCriteria.java b/vanilla-tests/src/main/java/fixtures/inheritance/passdiscriminator/models/MetricAlertCriteria.java index e413559f66..97a7ff9749 100644 --- a/vanilla-tests/src/main/java/fixtures/inheritance/passdiscriminator/models/MetricAlertCriteria.java +++ b/vanilla-tests/src/main/java/fixtures/inheritance/passdiscriminator/models/MetricAlertCriteria.java @@ -13,6 +13,7 @@ import com.fasterxml.jackson.annotation.JsonTypeId; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeName; +import java.util.LinkedHashMap; import java.util.Map; /** From 8263175692393f5dc7c12d3c8ebe6dc8afe0f52a Mon Sep 17 00:00:00 2001 From: alzimmermsft <48699787+alzimmermsft@users.noreply.github.com> Date: Tue, 21 May 2024 14:39:13 -0400 Subject: [PATCH 5/6] Fix test failing due to TypeSpec change and non-related codegen bug --- .../src/test/java/com/cadl/patch/PatchClientTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/typespec-tests/src/test/java/com/cadl/patch/PatchClientTest.java b/typespec-tests/src/test/java/com/cadl/patch/PatchClientTest.java index 09f498295a..25f3a118e0 100644 --- a/typespec-tests/src/test/java/com/cadl/patch/PatchClientTest.java +++ b/typespec-tests/src/test/java/com/cadl/patch/PatchClientTest.java @@ -132,7 +132,9 @@ public void testSerializationForHierarchicalProperty() throws JsonProcessingExce String json = BinaryData.fromObject(resource).toString(); JsonNode node = OBJECT_MAPPER.readTree(json); Assertions.assertEquals(JsonNodeType.NULL, node.get("fish").get("color").getNodeType()); - Assertions.assertEquals("shark", node.get("fish").get("kind").asText()); + // TODO (alzimmer): Added SawShark into the hierarchy for further validation but this brings up a bug where + // multi-level polymorphism does not generate correctly. Need to fix this in the future. + Assertions.assertEquals("shark", node.get("fish").get("sharktype").asText()); Assertions.assertEquals(2, node.get("fish").get("age").asInt()); } From 4cb8ee918cfacf85c5eb64c71f7a07100c428c2f Mon Sep 17 00:00:00 2001 From: alzimmermsft <48699787+alzimmermsft@users.noreply.github.com> Date: Wed, 22 May 2024 09:56:24 -0400 Subject: [PATCH 6/6] Remove empty line to test issue with formatting --- typespec-tests/tsp/patch.tsp | 1 - 1 file changed, 1 deletion(-) diff --git a/typespec-tests/tsp/patch.tsp b/typespec-tests/tsp/patch.tsp index d72493cb40..c641993e12 100644 --- a/typespec-tests/tsp/patch.tsp +++ b/typespec-tests/tsp/patch.tsp @@ -62,7 +62,6 @@ model Fish { model Shark extends Fish { kind: "shark"; sharktype: string; - weight?: int32; }