Skip to content

Commit

Permalink
simplify the serialization/deserialization hook (#5412)
Browse files Browse the repository at this point in the history
Fixes #5411
  • Loading branch information
ArcturusZhang authored Dec 20, 2024
1 parent 70f8ea5 commit fa488db
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -842,15 +842,15 @@ private List<MethodBodyStatement> BuildDeserializePropertiesStatements(ScopedApi

if (_additionalBinaryDataProperty != null)
{
var binaryDataDeserializationValue = ClientModelPlugin.Instance.TypeFactory.GetValueTypeDeserializationExpression(
var binaryDataDeserializationValue = ClientModelPlugin.Instance.TypeFactory.DeserializeJsonValue(
_additionalBinaryDataProperty.Type.ElementType.FrameworkType, jsonProperty.Value(), SerializationFormat.Default);
propertyDeserializationStatements.Add(
_additionalBinaryDataProperty.AsVariableExpression.AsDictionary(_additionalBinaryDataProperty.Type).Add(jsonProperty.Name(), binaryDataDeserializationValue));
}
else if (rawBinaryData != null)
{
var elementType = rawBinaryData.Type.Arguments[1].FrameworkType;
var rawDataDeserializationValue = ClientModelPlugin.Instance.TypeFactory.GetValueTypeDeserializationExpression(elementType, jsonProperty.Value(), SerializationFormat.Default);
var rawDataDeserializationValue = ClientModelPlugin.Instance.TypeFactory.DeserializeJsonValue(elementType, jsonProperty.Value(), SerializationFormat.Default);
propertyDeserializationStatements.Add(new IfStatement(_isNotEqualToWireConditionSnippet)
{
rawBinaryData.AsVariableExpression.AsDictionary(rawBinaryData.Type).Add(jsonProperty.Name(), rawDataDeserializationValue)
Expand Down Expand Up @@ -1267,11 +1267,11 @@ private ValueExpression CreateDeserializeValueExpression(CSharpType valueType, S
valueType switch
{
{ IsFrameworkType: true } when valueType.FrameworkType == typeof(Nullable<>) =>
ClientModelPlugin.Instance.TypeFactory.GetValueTypeDeserializationExpression(valueType.Arguments[0].FrameworkType, jsonElement, serializationFormat),
ClientModelPlugin.Instance.TypeFactory.DeserializeJsonValue(valueType.Arguments[0].FrameworkType, jsonElement, serializationFormat),
{ IsFrameworkType: true } =>
ClientModelPlugin.Instance.TypeFactory.GetValueTypeDeserializationExpression(valueType.FrameworkType, jsonElement, serializationFormat),
ClientModelPlugin.Instance.TypeFactory.DeserializeJsonValue(valueType.FrameworkType, jsonElement, serializationFormat),
{ IsEnum: true } =>
valueType.ToEnum(ClientModelPlugin.Instance.TypeFactory.GetValueTypeDeserializationExpression(valueType.UnderlyingEnumType!, jsonElement, serializationFormat)),
valueType.ToEnum(ClientModelPlugin.Instance.TypeFactory.DeserializeJsonValue(valueType.UnderlyingEnumType!, jsonElement, serializationFormat)),
_ => valueType.Deserialize(jsonElement, _mrwOptionsParameterSnippet)
};

Expand Down Expand Up @@ -1584,48 +1584,43 @@ private MethodBodyStatement CreateValueSerializationStatement(
SerializationFormat serializationFormat,
ValueExpression value)
{
// append the `.Value` if needed (when the type is nullable and a value type)
value = value.NullableStructValue(type);

// now we just need to focus on how we serialize a value
if (type.IsFrameworkType)
return ClientModelPlugin.Instance.TypeFactory.SerializeValueType(type, serializationFormat, value, type.FrameworkType, _utf8JsonWriterSnippet, _mrwOptionsParameterSnippet);
return ClientModelPlugin.Instance.TypeFactory.SerializeJsonValue(type.FrameworkType, value, _utf8JsonWriterSnippet, _mrwOptionsParameterSnippet, serializationFormat);

if (!type.IsEnum)
return _utf8JsonWriterSnippet.WriteObjectValue(value.As(type), options: _mrwOptionsParameterSnippet);

var enumerableSnippet = value.NullableStructValue(type).As(type);
if (type.IsStruct) //is extensible
{
if (type.UnderlyingEnumType.Equals(typeof(string)))
return _utf8JsonWriterSnippet.WriteStringValue(enumerableSnippet.Invoke(nameof(ToString)));
return _utf8JsonWriterSnippet.WriteStringValue(value.Invoke(nameof(ToString)));

return _utf8JsonWriterSnippet.WriteNumberValue(enumerableSnippet.Invoke($"ToSerial{type.UnderlyingEnumType.Name}"));
return _utf8JsonWriterSnippet.WriteNumberValue(value.Invoke($"ToSerial{type.UnderlyingEnumType.Name}"));
}
else
{
if (type.UnderlyingEnumType.Equals(typeof(int)))
// when the fixed enum is implemented as int, we cast to the value
return _utf8JsonWriterSnippet.WriteNumberValue(enumerableSnippet.CastTo(type.UnderlyingEnumType));
return _utf8JsonWriterSnippet.WriteNumberValue(value.CastTo(type.UnderlyingEnumType));

if (type.UnderlyingEnumType.Equals(typeof(string)))
return _utf8JsonWriterSnippet.WriteStringValue(enumerableSnippet.Invoke($"ToSerial{type.UnderlyingEnumType.Name}"));
return _utf8JsonWriterSnippet.WriteStringValue(value.Invoke($"ToSerial{type.UnderlyingEnumType.Name}"));

return _utf8JsonWriterSnippet.WriteNumberValue(enumerableSnippet.Invoke($"ToSerial{type.UnderlyingEnumType.Name}"));
return _utf8JsonWriterSnippet.WriteNumberValue(value.Invoke($"ToSerial{type.UnderlyingEnumType.Name}"));
}
}

internal static MethodBodyStatement SerializeValueTypeCore(
CSharpType type,
SerializationFormat serializationFormat,
ValueExpression value,
internal static MethodBodyStatement SerializeJsonValueCore(
Type valueType,
ValueExpression value,
ScopedApi<Utf8JsonWriter> utf8JsonWriter,
ScopedApi<ModelReaderWriterOptions> mrwOptionsParameter)
ScopedApi<ModelReaderWriterOptions> mrwOptionsParameter,
SerializationFormat serializationFormat)
{
if (valueType == typeof(Nullable<>))
{
valueType = type.Arguments[0].FrameworkType;
}

value = value.NullableStructValue(type);

return valueType switch
{
var t when t == typeof(JsonElement) =>
Expand Down Expand Up @@ -1656,7 +1651,7 @@ var t when ValueTypeIsNumber(t) =>
};
}

internal static ValueExpression GetValueTypeDeserializationExpressionCore(
internal static ValueExpression DeserializeJsonValueCore(
Type valueType,
ScopedApi<JsonElement> element,
SerializationFormat format)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,16 +118,15 @@ public ClientProvider CreateClient(InputClient inputClient)
return methods;
}

public virtual ValueExpression GetValueTypeDeserializationExpression(Type valueType, ScopedApi<JsonElement> element, SerializationFormat format)
=> MrwSerializationTypeDefinition.GetValueTypeDeserializationExpressionCore(valueType, element, format);
public virtual ValueExpression DeserializeJsonValue(Type valueType, ScopedApi<JsonElement> element, SerializationFormat format)
=> MrwSerializationTypeDefinition.DeserializeJsonValueCore(valueType, element, format);

public virtual MethodBodyStatement SerializeValueType(
CSharpType type,
SerializationFormat serializationFormat,
ValueExpression value,
public virtual MethodBodyStatement SerializeJsonValue(
Type valueType,
ValueExpression value,
ScopedApi<Utf8JsonWriter> utf8JsonWriter,
ScopedApi<ModelReaderWriterOptions> mrwOptionsParameter)
=> MrwSerializationTypeDefinition.SerializeValueTypeCore(type, serializationFormat, value, valueType, utf8JsonWriter, mrwOptionsParameter);
ScopedApi<ModelReaderWriterOptions> mrwOptionsParameter,
SerializationFormat serializationFormat)
=> MrwSerializationTypeDefinition.SerializeJsonValueCore(valueType, value, utf8JsonWriter, mrwOptionsParameter, serializationFormat);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -712,7 +712,7 @@ public void TestIntSerializationStatement(
[TestCase(typeof(sbyte), SerializationFormat.Default, ExpectedResult = "foo.GetSByte()")]
public string TestIntDeserializeExpression(Type type, SerializationFormat format)
{
var expr = MrwSerializationTypeDefinition.GetValueTypeDeserializationExpressionCore(type, new ScopedApi<JsonElement>(new VariableExpression(typeof(JsonElement), "foo")), format);
var expr = MrwSerializationTypeDefinition.DeserializeJsonValueCore(type, new ScopedApi<JsonElement>(new VariableExpression(typeof(JsonElement), "foo")), format);
return expr.ToDisplayString();
}

Expand Down

0 comments on commit fa488db

Please sign in to comment.