Skip to content

Add virtual DeserializeXmlValue and SerializeXmlValue APIs to ScmTypeFactory#10186

Draft
Copilot wants to merge 5 commits intomainfrom
copilot/add-serialize-deserialize-xml-apis
Draft

Add virtual DeserializeXmlValue and SerializeXmlValue APIs to ScmTypeFactory#10186
Copilot wants to merge 5 commits intomainfrom
copilot/add-serialize-deserialize-xml-apis

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 27, 2026

ScmTypeFactory has virtual DeserializeJsonValue/SerializeJsonValue for JSON but lacks XML equivalents, preventing extending generators from overriding XML serialization for types like Etag.

Changes

  • ScmTypeFactory.cs — Added virtual methods DeserializeXmlValue (returns ValueExpression) and SerializeXmlValue (returns ValueExpression), enabling extending generators to override XML serialization
  • MrwSerializationTypeDefinition.Xml.cs — Replaced private CreateXmlDeserializeValueExpression and CreateXmlSerializeValueExpression with internal static core methods (DeserializeXmlValueCore, SerializeXmlValueCore). Updated callers to route through ScmCodeModelGenerator.Instance.TypeFactory for overrideability, matching the JSON pattern.
  • XmlDeserializationTests.cs — Added unit tests for DeserializeXmlValueCore covering primitive types, DateTimeOffset, and TimeSpan
  • XmlSerializationTests.cs — Added unit tests for SerializeXmlValueCore covering primitive types, DateTimeOffset, and TimeSpan. Added TestData-validated override tests demonstrating custom type factory overrides for both serialize and deserialize directions.
// Extending generators can now override XML value serialization:
public override ValueExpression DeserializeXmlValue(
    CSharpType valueType,
    ScopedApi<XElement> element,
    ScopedApi<ModelReaderWriterOptions> mrwOptionsParameter,
    SerializationFormat format)
{
    if (valueType.FrameworkType == typeof(ETag))
        return New.Instance<ETag>(element.Value());

    return base.DeserializeXmlValue(valueType, element, mrwOptionsParameter, format);
}

⌨️ Start Copilot coding agent tasks without leaving your editor — available in VS Code, Visual Studio, JetBrains IDEs and Eclipse.

…cmTypeFactory

Agent-Logs-Url: https://github.com/microsoft/typespec/sessions/d5c279ee-c360-42a7-970b-30add42ea465

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>
@microsoft-github-policy-service microsoft-github-policy-service bot added the emitter:client:csharp Issue for the C# client emitter: @typespec/http-client-csharp label Mar 27, 2026
Agent-Logs-Url: https://github.com/microsoft/typespec/sessions/d5c279ee-c360-42a7-970b-30add42ea465

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>
Copilot AI changed the title [WIP] Add deserialize and serialize XML value APIs for XML serialization Add virtual DeserializeXmlValue and SerializeXmlValue APIs to ScmTypeFactory Mar 27, 2026
Copilot AI requested a review from jorgerangel-msft March 27, 2026 22:15
Agent-Logs-Url: https://github.com/microsoft/typespec/sessions/4d2deae7-13ce-4e8a-bf7c-0084380adacb

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

@jorgerangel-msft jorgerangel-msft left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot ensure all tests are passing. Also rerun the Generate.ps1 script

};
}

internal static ValueExpression DeserializeXmlValueCore(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot can we just replace the CreateXmlDeserializeValueExpression method with this method? The contents should be unchanged from CreateXmlDeserializeValueExpression.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 4772098. CreateXmlDeserializeValueExpression has been replaced with DeserializeXmlValueCore (internal static), and callers now route through ScmCodeModelGenerator.Instance.TypeFactory.DeserializeXmlValue(...) matching the JSON pattern.

return CreateXmlDeserializePrimitiveExpression(element, valueType, format);
}

internal static MethodBodyStatement SerializeXmlValueCore(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot can we just replace the CreateXmlSerializeValueExpression method with this? The body should be the same as CreateXmlSerializeValueExpression.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 4772098. CreateXmlSerializeValueExpression has been replaced with SerializeXmlValueCore (internal static, returning ValueExpression with the same body), and callers now route through ScmCodeModelGenerator.Instance.TypeFactory.SerializeXmlValue(...).

};
}

internal static ValueExpression SerializeXmlValueExpressionCore(ValueExpression value, CSharpType valueType, SerializationFormat serializationFormat)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot why is this needed?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed in 4772098. It was a duplicate of CreateXmlSerializeValueExpression. Now SerializeXmlValueCore returns ValueExpression directly (same body as the old method), so SerializeXmlValueExpressionCore is no longer needed.

ScopedApi<XElement> element,
ScopedApi<ModelReaderWriterOptions> mrwOptionsParameter,
SerializationFormat format)
=> MrwSerializationTypeDefinition.DeserializeXmlValueCore(valueType, element, mrwOptionsParameter, format);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot add indentation to the lambda

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 4772098.

ScopedApi<XmlWriter> xmlWriter,
ScopedApi<ModelReaderWriterOptions> mrwOptionsParameter,
SerializationFormat serializationFormat)
=> MrwSerializationTypeDefinition.SerializeXmlValueCore(valueType, value, xmlWriter, mrwOptionsParameter, serializationFormat);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot add indentation to the lambda

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 4772098.

[TestCase(typeof(byte), SerializationFormat.Default, ExpectedResult = "((byte)((int)foo))")]
[TestCase(typeof(sbyte), SerializationFormat.Default, ExpectedResult = "((sbyte)((int)foo))")]
[TestCase(typeof(short), SerializationFormat.Default, ExpectedResult = "((short)((int)foo))")]
public string TestDeserializeXmlValueCore_PrimitiveTypes(Type type, SerializationFormat format)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot this new test should go in XmlDeserializationTests

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 4772098 — deserialization tests moved to XmlDeserializationTests.cs.

}

[Test]
public void TestSerializeXmlValueCore_Int()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot this new test should go in XmlSserializationTests

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 4772098 — serialization tests moved to XmlSerializationTests.cs.

}

[Test]
public void TestSerializeXmlValueCore_String()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot use TestData to validate the serialization tests.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 4772098. Added TestData-based validation for two override tests: SerializeXmlValueOverride_CustomTypeSerialization and DeserializeXmlValueOverride_CustomTypeDeserialization, which compare full generated output against expected .cs files.


[TestCase(SerializationFormat.Duration_ISO8601)]
[TestCase(SerializationFormat.Duration_Constant)]
public void TestSerializeXmlValueCore_TimeSpan(SerializationFormat format)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot we should also add a test case where we override the new APIs and add custom serialization for a new type, or existing type.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 4772098. Added two override tests using Moq:

  • SerializeXmlValueOverride_CustomTypeSerialization — overrides SerializeXmlValue for string type to return value.ToString() and validates output with TestData
  • DeserializeXmlValueOverride_CustomTypeDeserialization — overrides DeserializeXmlValue for string type to return element.ToString() and validates output with TestData

…ds, move tests to XML test files, add override tests

Agent-Logs-Url: https://github.com/microsoft/typespec/sessions/fb4989f3-4f35-4758-9fbc-8e1a87f8c2c4

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 27, 2026

@copilot ensure all tests are passing. Also rerun the Generate.ps1 script

Done in 4772098. All 1264 tests pass and Generate.ps1 ran successfully with no diff in generated output.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

emitter:client:csharp Issue for the C# client emitter: @typespec/http-client-csharp

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Deserialize + Serialize Xml Value APIs for XML Serialization

2 participants