Skip to content

Commit

Permalink
Pass through ModelReaderWriter options to SerializationHooks (#4665)
Browse files Browse the repository at this point in the history
  • Loading branch information
nisha-bhatia committed May 10, 2024
1 parent abb0a20 commit 213b563
Show file tree
Hide file tree
Showing 24 changed files with 413 additions and 278 deletions.
Expand Up @@ -247,7 +247,7 @@ private static MethodBodyStatement WritePropertySerialization(Utf8JsonWriterExpr
{
utf8JsonWriter.WritePropertyName(serialization.SerializedName),
serialization.CustomSerializationMethodName is {} serializationMethodName
? InvokeCustomSerializationMethod(serializationMethodName, utf8JsonWriter)
? InvokeCustomSerializationMethod(serializationMethodName, utf8JsonWriter, options)
: SerializeExpression(utf8JsonWriter, serialization.ValueSerialization, serialization.EnumerableValue ?? serialization.Value, options)
};
}
Expand Down
17 changes: 13 additions & 4 deletions src/AutoRest.CSharp/Common/Output/Expressions/Snippets.cs
Expand Up @@ -4,6 +4,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.Json;
using AutoRest.CSharp.Common.Input;
using AutoRest.CSharp.Common.Output.Expressions;
using AutoRest.CSharp.Common.Output.Expressions.KnownValueExpressions;
Expand All @@ -12,6 +14,7 @@
using AutoRest.CSharp.Generation.Types;
using AutoRest.CSharp.Generation.Writers;
using AutoRest.CSharp.Output.Models.Types;
using static AutoRest.CSharp.Common.Input.Configuration;

namespace AutoRest.CSharp.Common.Output.Models
{
Expand Down Expand Up @@ -92,13 +95,19 @@ public static StreamExpression InvokeFileOpenRead(string filePath)
public static StreamExpression InvokeFileOpenWrite(string filePath)
=> new(new InvokeStaticMethodExpression(typeof(System.IO.File), nameof(System.IO.File.OpenWrite), new[] { Literal(filePath) }));

// Expected signature: MethodName(Utf8JsonWriter writer);
public static MethodBodyStatement InvokeCustomSerializationMethod(string methodName, Utf8JsonWriterExpression utf8JsonWriter)
=> new InvokeInstanceMethodStatement(null, methodName, utf8JsonWriter);
// Expected signature: MethodName(Utf8JsonWriter writer, ModelReaderWriterOptions? options);
public static MethodBodyStatement InvokeCustomSerializationMethod(string methodName, Utf8JsonWriterExpression utf8JsonWriter, ModelReaderWriterOptionsExpression? options)
{
// If options is null, the method signature should not include the parameter
return options is null
? new InvokeInstanceMethodStatement(null, methodName, utf8JsonWriter)
: new InvokeInstanceMethodStatement(null, methodName, utf8JsonWriter, options);
}

// TODO: https://github.com/Azure/autorest.csharp/issues/4633
// Expected signature: MethodName(StringBuilder builder);
public static MethodBodyStatement InvokeCustomBicepSerializationMethod(string methodName, StringBuilderExpression stringBuilder)
=> new InvokeInstanceMethodStatement(null, methodName, stringBuilder);
=> new InvokeInstanceMethodStatement(null, methodName, stringBuilder);

// Expected signature: MethodName(JsonProperty property, ref T optional)
public static MethodBodyStatement InvokeCustomDeserializationMethod(string methodName, JsonPropertyExpression jsonProperty, CodeWriterDeclaration variable)
Expand Down
Expand Up @@ -3,6 +3,7 @@

#nullable disable

using System.ClientModel.Primitives;
using System.Runtime.CompilerServices;
using System.Text.Json;
using Azure.Core;
Expand Down Expand Up @@ -31,7 +32,7 @@ public partial class ModelToAddAdditionalSerializableProperty
public int RequiredInt { get; set; }

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void WriteRequiredIntValue(Utf8JsonWriter writer)
private void WriteRequiredIntValue(Utf8JsonWriter writer, ModelReaderWriterOptions options)
{
writer.WriteStringValue(RequiredInt.ToString());
}
Expand All @@ -43,7 +44,7 @@ private static void ReadRequiredIntValue(JsonProperty property, ref int required
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void WriteRequiredIntOnBaseValue(Utf8JsonWriter writer)
private void WriteRequiredIntOnBaseValue(Utf8JsonWriter writer, ModelReaderWriterOptions options)
{
writer.WriteStringValue(RequiredIntOnBase.ToString());
}
Expand Down
Expand Up @@ -28,7 +28,7 @@ void IJsonModel<ModelToAddAdditionalSerializableProperty>.Write(Utf8JsonWriter w

writer.WriteStartObject();
writer.WritePropertyName("requiredInt"u8);
WriteRequiredIntValue(writer);
WriteRequiredIntValue(writer, options);
writer.WritePropertyName("additionalSerializableProperty"u8);
writer.WriteNumberValue(AdditionalSerializableProperty);
if (Optional.IsDefined(AdditionalNullableSerializableProperty))
Expand All @@ -44,7 +44,7 @@ void IJsonModel<ModelToAddAdditionalSerializableProperty>.Write(Utf8JsonWriter w
}
}
writer.WritePropertyName("requiredIntOnBase"u8);
WriteRequiredIntOnBaseValue(writer);
WriteRequiredIntOnBaseValue(writer, options);
if (Optional.IsDefined(OptionalInt))
{
writer.WritePropertyName("optionalInt"u8);
Expand Down
32 changes: 32 additions & 0 deletions test/TestProjects/Inheritance/Custom/SomeProperties.cs
@@ -0,0 +1,32 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#nullable disable

using System.Runtime.CompilerServices;
using System.Text.Json;
using Azure.Core;

namespace Inheritance.Models
{
/// <summary>
/// The SomeProperties class.
/// </summary>
[CodeGenSerialization(nameof(SomeProperty), SerializationValueHook = nameof(SerializationMethodHook))]
public partial class SomeProperties : IUtf8JsonSerializable
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void SerializationMethodHook(Utf8JsonWriter writer)
{
writer.WriteStringValue("OverloadSucceeded");
}

/// <summary>
/// Forwards call
/// </summary>
/// <param name="writer"></param>
#pragma warning disable AZC0014 // Types from certain namespaces should not be exposed as part of public API surface.
public void CallWrite(Utf8JsonWriter writer) => ((IUtf8JsonSerializable)this).Write(writer);
#pragma warning restore AZC0014 // Types from certain namespaces should not be exposed as part of public API surface.
}
}
Expand Up @@ -82,7 +82,7 @@ void IUtf8JsonSerializable.Write(Utf8JsonWriter writer)
if (Optional.IsDefined(SomeProperty))
{
writer.WritePropertyName("SomeProperty"u8);
writer.WriteStringValue(SomeProperty);
SerializationMethodHook(writer);
}
if (Optional.IsDefined(SomeOtherProperty))
{
Expand Down
Expand Up @@ -82,7 +82,7 @@ void IUtf8JsonSerializable.Write(Utf8JsonWriter writer)
if (Optional.IsDefined(SomeProperty))
{
writer.WritePropertyName("SomeProperty"u8);
writer.WriteStringValue(SomeProperty);
SerializationMethodHook(writer);
}
if (Optional.IsDefined(SomeOtherProperty))
{
Expand Down
Expand Up @@ -82,7 +82,7 @@ void IUtf8JsonSerializable.Write(Utf8JsonWriter writer)
if (Optional.IsDefined(SomeProperty))
{
writer.WritePropertyName("SomeProperty"u8);
writer.WriteStringValue(SomeProperty);
SerializationMethodHook(writer);
}
if (Optional.IsDefined(SomeOtherProperty))
{
Expand Down
Expand Up @@ -19,7 +19,7 @@ void IUtf8JsonSerializable.Write(Utf8JsonWriter writer)
if (Optional.IsDefined(SomeProperty))
{
writer.WritePropertyName("SomeProperty"u8);
writer.WriteStringValue(SomeProperty);
SerializationMethodHook(writer);
}
if (Optional.IsDefined(SomeOtherProperty))
{
Expand Down
Expand Up @@ -3,6 +3,7 @@

#nullable disable

using System.ClientModel.Primitives;
using System.Runtime.CompilerServices;
using System.Text.Json;
using Azure.Core;
Expand All @@ -20,7 +21,7 @@ public partial class Dog : Pet
public Pet Friend { get; set; }

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void SerializeBarkProperty(Utf8JsonWriter writer)
private void SerializeBarkProperty(Utf8JsonWriter writer, ModelReaderWriterOptions options)
{
writer.WriteStringValue(Bark.ToUpperInvariant());
}
Expand Down
7 changes: 4 additions & 3 deletions test/TestProjects/MgmtCustomizations/src/Customization/Pet.cs
Expand Up @@ -4,6 +4,7 @@
#nullable disable

using System;
using System.ClientModel.Primitives;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Text.Json;
Expand All @@ -30,7 +31,7 @@ public abstract partial class Pet
public IDictionary<string, string> Tags { get; set; }

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void SerializeSizeProperty(Utf8JsonWriter writer)
internal void SerializeSizeProperty(Utf8JsonWriter writer, ModelReaderWriterOptions options)
{
writer.WriteStringValue(Size.ToString());
}
Expand All @@ -49,13 +50,13 @@ internal static void DeserializeSizeProperty(JsonProperty property, ref int size
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void SerializeDateOfBirthProperty(Utf8JsonWriter writer)
internal void SerializeDateOfBirthProperty(Utf8JsonWriter writer, ModelReaderWriterOptions options)
{
writer.WriteStringValue(DateOfBirth.Value, "yyyy-MM-dd HH:mm");
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void SerializeColorProperty(Utf8JsonWriter writer)
internal void SerializeColorProperty(Utf8JsonWriter writer, ModelReaderWriterOptions options)
{
writer.WriteStringValue(Color.ToString());
}
Expand Down
Expand Up @@ -3,6 +3,7 @@

#nullable disable

using System.ClientModel.Primitives;
using System.Runtime.CompilerServices;
using System.Text.Json;
using Azure.Core;
Expand All @@ -13,7 +14,7 @@ namespace MgmtCustomizations
public partial class PetStoreData
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void WriteId(Utf8JsonWriter writer)
internal void WriteId(Utf8JsonWriter writer, ModelReaderWriterOptions options)
{
if (Id != null)
writer.WriteStringValue(Id);
Expand Down
Expand Up @@ -49,11 +49,11 @@ void IJsonModel<Cat>.Write(Utf8JsonWriter writer, ModelReaderWriterOptions optio
writer.WriteStringValue(Name);
}
writer.WritePropertyName("size"u8);
SerializeSizeProperty(writer);
SerializeSizeProperty(writer, options);
if (Optional.IsDefined(DateOfBirth))
{
writer.WritePropertyName("dateOfBirth"u8);
SerializeDateOfBirthProperty(writer);
SerializeDateOfBirthProperty(writer, options);
}
if (Optional.IsCollectionDefined(Tags))
{
Expand All @@ -71,7 +71,7 @@ void IJsonModel<Cat>.Write(Utf8JsonWriter writer, ModelReaderWriterOptions optio
if (Optional.IsDefined(Color))
{
writer.WritePropertyName("color"u8);
SerializeColorProperty(writer);
SerializeColorProperty(writer, options);
}
writer.WriteEndObject();
if (options.Format != "W" && _serializedAdditionalRawData != null)
Expand Down
Expand Up @@ -39,11 +39,11 @@ void IJsonModel<Dog>.Write(Utf8JsonWriter writer, ModelReaderWriterOptions optio
writer.WriteStringValue(Name);
}
writer.WritePropertyName("size"u8);
SerializeSizeProperty(writer);
SerializeSizeProperty(writer, options);
if (Optional.IsDefined(DateOfBirth))
{
writer.WritePropertyName("dateOfBirth"u8);
SerializeDateOfBirthProperty(writer);
SerializeDateOfBirthProperty(writer, options);
}
if (Optional.IsCollectionDefined(Tags))
{
Expand All @@ -61,14 +61,14 @@ void IJsonModel<Dog>.Write(Utf8JsonWriter writer, ModelReaderWriterOptions optio
if (Optional.IsDefined(Color))
{
writer.WritePropertyName("color"u8);
SerializeColorProperty(writer);
SerializeColorProperty(writer, options);
}
writer.WritePropertyName("dog"u8);
writer.WriteStartObject();
if (Optional.IsDefined(Bark))
{
writer.WritePropertyName("bark"u8);
SerializeBarkProperty(writer);
SerializeBarkProperty(writer, options);
}
if (Optional.IsDefined(Friend))
{
Expand Down
Expand Up @@ -34,11 +34,11 @@ void IJsonModel<Pet>.Write(Utf8JsonWriter writer, ModelReaderWriterOptions optio
writer.WriteStringValue(Name);
}
writer.WritePropertyName("size"u8);
SerializeSizeProperty(writer);
SerializeSizeProperty(writer, options);
if (Optional.IsDefined(DateOfBirth))
{
writer.WritePropertyName("dateOfBirth"u8);
SerializeDateOfBirthProperty(writer);
SerializeDateOfBirthProperty(writer, options);
}
if (Optional.IsCollectionDefined(Tags))
{
Expand All @@ -56,7 +56,7 @@ void IJsonModel<Pet>.Write(Utf8JsonWriter writer, ModelReaderWriterOptions optio
if (Optional.IsDefined(Color))
{
writer.WritePropertyName("color"u8);
SerializeColorProperty(writer);
SerializeColorProperty(writer, options);
}
writer.WriteEndObject();
if (options.Format != "W" && _serializedAdditionalRawData != null)
Expand Down
Expand Up @@ -34,11 +34,11 @@ void IJsonModel<Pet>.Write(Utf8JsonWriter writer, ModelReaderWriterOptions optio
writer.WriteStringValue(Name);
}
writer.WritePropertyName("size"u8);
SerializeSizeProperty(writer);
SerializeSizeProperty(writer, options);
if (Optional.IsDefined(DateOfBirth))
{
writer.WritePropertyName("dateOfBirth"u8);
SerializeDateOfBirthProperty(writer);
SerializeDateOfBirthProperty(writer, options);
}
if (Optional.IsCollectionDefined(Tags))
{
Expand All @@ -56,7 +56,7 @@ void IJsonModel<Pet>.Write(Utf8JsonWriter writer, ModelReaderWriterOptions optio
if (Optional.IsDefined(Color))
{
writer.WritePropertyName("color"u8);
SerializeColorProperty(writer);
SerializeColorProperty(writer, options);
}
writer.WriteEndObject();
if (options.Format != "W" && _serializedAdditionalRawData != null)
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

41 changes: 40 additions & 1 deletion test/UnbrandedProjects.Tests/CustomizedUnbrandedTests.cs
Expand Up @@ -2,11 +2,14 @@
// Licensed under the MIT License.

using CustomizedTypeSpec.Models;
using Inheritance.Models;
using NUnit.Framework;
using System;
using System.ClientModel.Primitives;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text.Json;
using System.Text;

namespace CustomizedTypeSpec.Tests
{
Expand Down Expand Up @@ -67,5 +70,41 @@ public void VerifyCodeGenSuppress()
var constructor1 = t.GetConstructor(parameterTypes1);
Assert.Null(constructor1);
}

[Test]
public void VerifyCodeGenSerializationMethodHookWithMRW()
{
SuperRoundTripModel model = new SuperRoundTripModel
(
"requiredSuperString",
1
);

BinaryData binaryData = ModelReaderWriter.Write(model);
string jsonString = binaryData.ToString();
Assert.IsTrue(jsonString.Contains("7"));
Assert.IsFalse(jsonString.Contains("1"));
}

[Test]
public void VerifyCodeGenSerializationMethodHookWithoutMRW()
{
SomeProperties model = new SomeProperties();
model.SomeProperty = "SomeProperty";
model.SomeOtherProperty = "SomeOtherProperty";

// Create a MemoryStream to hold the JSON data
using var stream = new MemoryStream();
using (var writer = new Utf8JsonWriter(stream))
{
// Call the Write method
model.CallWrite(writer);
}

// Get the JSON string
string jsonString = Encoding.UTF8.GetString(stream.ToArray());
Assert.IsTrue(jsonString.Contains("{\"SomeProperty\":\"OverloadSucceeded\""));
Assert.IsFalse(jsonString.Contains("{\"SomeProperty\":\"SomeProperty\""));
}
}
}

0 comments on commit 213b563

Please sign in to comment.