Skip to content

Commit

Permalink
fix: keep nil values during (de)serialization (#14127)
Browse files Browse the repository at this point in the history
  • Loading branch information
mirkoSekulic authored Nov 21, 2024
1 parent 3c0cfab commit 2664fed
Show file tree
Hide file tree
Showing 18 changed files with 439 additions and 367 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ private void ParseFieldProperty(ElementMetadata element, StringBuilder classBuil
else
{
elementOrder += 1;
AddXmlElementAnnotation(element, classBuilder, elementOrder);
AddXmlElementAnnotation(element, classBuilder, elementOrder, !isValueType && (element.Nillable ?? false));

// Temporary fix - as long as we use System.Text.Json for serialization and Newtonsoft.Json for
// deserialization, we need both JsonProperty and JsonPropertyName annotations.
Expand Down Expand Up @@ -265,16 +265,21 @@ private void ParseGroupProperty(ElementMetadata element, StringBuilder classBuil
}
}

private void AddXmlElementAnnotation(ElementMetadata element, StringBuilder classBuilder, int elementOrder)
private void AddXmlElementAnnotation(ElementMetadata element, StringBuilder classBuilder, int elementOrder, bool addNillableAttribute = false)
{
if (element.OrderOblivious)
string additionalAttributeParams = string.Empty;
if (!element.OrderOblivious)
{
classBuilder.AppendLine($"""{Indent(2)}[XmlElement("{element.XName}")]""");
additionalAttributeParams += $", Order = {elementOrder}";
}
else

if (addNillableAttribute)
{
classBuilder.AppendLine($"""{Indent(2)}[XmlElement("{element.XName}", Order = {elementOrder})]""");
additionalAttributeParams += ", IsNullable = true";
}


classBuilder.AppendLine($"""{Indent(2)}[XmlElement("{element.XName}"{additionalAttributeParams})]""");
}

private void AddShouldSerializeForTagContent(ElementMetadata element, StringBuilder classBuilder, ModelMetadata modelMetadata)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public void JsonSchemaWithStringFieldInUriFormatShouldConvertToCSharp(string jso
.Then.CompiledAssembly.Should().NotBeNull();
}

private void GeneratedClassesShouldBeEquivalentToExpected(string expectedCsharpClassPath)
private void GeneratedClassesShouldBeEquivalentToExpected(string expectedCsharpClassPath, bool overwriteExpected = false)
{
string expectedClasses = SharedResourcesHelper.LoadTestDataAsString(expectedCsharpClassPath);

Expand All @@ -86,7 +86,10 @@ private void GeneratedClassesShouldBeEquivalentToExpected(string expectedCsharpC
_testOutput.WriteLine(CSharpClasses);

// Save the current generated classes to the expected file so they can be compared with git diff.
SharedResourcesHelper.WriteUpdatedTestData(expectedCsharpClassPath, CSharpClasses);
if (overwriteExpected)
{
SharedResourcesHelper.WriteUpdatedTestData(expectedCsharpClassPath, CSharpClasses);
}

var expectedAssembly = Compiler.CompileToAssembly(expectedClasses);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.IO;
using System.Text;
using System.Xml.Serialization;
using SharedResources.Tests;

namespace DataModeling.Tests.Utils
{
Expand All @@ -20,7 +21,7 @@ public static object Deserialize(string xml, Type type)
public static string SerializeXml(object o)
{
var xmlSerializer = new XmlSerializer(o.GetType());
using var textWriter = new StringWriter();
using var textWriter = new Utf8StringWriter();
xmlSerializer.Serialize(textWriter, o);
return textWriter.ToString();
}
Expand Down
46 changes: 46 additions & 0 deletions backend/tests/DataModeling.Tests/XmlDeserializeSerializeTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System;
using System.Linq;
using System.Xml.Linq;
using System.Xml.Serialization;
using DataModeling.Tests.BaseClasses;
using DataModeling.Tests.Utils;
using FluentAssertions;
using SharedResources.Tests;
using Xunit;

namespace DataModeling.Tests;

public class XmlDeserializeSerializeTests : CsharpModelConversionTestsBase<XmlDeserializeSerializeTests>
{
[Theory]
[InlineData("Model/XmlSchema/XsAll/xsall-example.xsd", "Model/Xml/XsAll/xsall-example-nillable-sample.xml")]
public void XmlDeserializeSerializeShouldKeepNillValue(string xsdSchemaPath, string xmlPath)
{
Given.That.XsdSchemaLoaded(xsdSchemaPath)
.When.LoadedXsdSchemaConvertedToJsonSchema()
.And.ConvertedJsonSchemaConvertedToModelMetadata()
.And.ModelMetadataConvertedToCsharpClass()
.And.CSharpClassesCompiledToAssembly()
.Then.CompiledAssembly.Should().NotBeNull();

And.DeserializeAndSerializeShouldProduceSameXml(xmlPath);
}

private void DeserializeAndSerializeShouldProduceSameXml(string xmlPath)
{
Type csharpType = CompiledAssembly.Types().Single(type => type.CustomAttributes.Any(att => att.AttributeType == typeof(XmlRootAttribute)));

string loadedXml = SharedResourcesHelper.LoadTestDataAsString(xmlPath);

// Deserialize xml to new object of type csharpType
object deserializedObject = SerializationHelper.Deserialize(loadedXml, csharpType);

// serialize xml back to string
string serializedXml = SerializationHelper.SerializeXml(deserializedObject);

// Compare the original xml with the serialized xml
var expected = XDocument.Parse(loadedXml);
var result = XDocument.Parse(serializedXml);
Assert.True(XNode.DeepEquals(expected, result));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,12 @@ public class Applikasjon
[JsonPropertyName("beskrivelse")]
public string beskrivelse { get; set; }

[XmlElement("miljoe", Order = 6)]
[XmlElement("miljoe", Order = 6, IsNullable = true)]
[JsonProperty("miljoe")]
[JsonPropertyName("miljoe")]
public string miljoe { get; set; }

[XmlElement("nettleserApplikasjonWebadresse", Order = 7)]
[XmlElement("nettleserApplikasjonWebadresse", Order = 7, IsNullable = true)]
[JsonProperty("nettleserApplikasjonWebadresse")]
[JsonPropertyName("nettleserApplikasjonWebadresse")]
public string nettleserApplikasjonWebadresse { get; set; }
Expand All @@ -77,32 +77,32 @@ public class Applikasjon

public class APIRessurs
{
[XmlElement("profile", Order = 1)]
[XmlElement("profile", Order = 1, IsNullable = true)]
[JsonProperty("profile")]
[JsonPropertyName("profile")]
public string profile { get; set; }

[XmlElement("organizationReportee", Order = 2)]
[XmlElement("organizationReportee", Order = 2, IsNullable = true)]
[JsonProperty("organizationReportee")]
[JsonPropertyName("organizationReportee")]
public string organizationReportee { get; set; }

[XmlElement("meldingsboks", Order = 3)]
[XmlElement("meldingsboks", Order = 3, IsNullable = true)]
[JsonProperty("meldingsboks")]
[JsonPropertyName("meldingsboks")]
public string meldingsboks { get; set; }

[XmlElement("lookup", Order = 4)]
[XmlElement("lookup", Order = 4, IsNullable = true)]
[JsonProperty("lookup")]
[JsonPropertyName("lookup")]
public string lookup { get; set; }

[XmlElement("broker", Order = 5)]
[XmlElement("broker", Order = 5, IsNullable = true)]
[JsonProperty("broker")]
[JsonPropertyName("broker")]
public string broker { get; set; }

[XmlElement("autorisasjon", Order = 6)]
[XmlElement("autorisasjon", Order = 6, IsNullable = true)]
[JsonProperty("autorisasjon")]
[JsonPropertyName("autorisasjon")]
public string autorisasjon { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,12 @@ public class Tjenesteeier
[JsonPropertyName("sektor")]
public string sektor { get; set; }

[XmlElement("navnNynorsk", Order = 4)]
[XmlElement("navnNynorsk", Order = 4, IsNullable = true)]
[JsonProperty("navnNynorsk")]
[JsonPropertyName("navnNynorsk")]
public string navnNynorsk { get; set; }

[XmlElement("navnEngelsk", Order = 5)]
[XmlElement("navnEngelsk", Order = 5, IsNullable = true)]
[JsonProperty("navnEngelsk")]
[JsonPropertyName("navnEngelsk")]
public string navnEngelsk { get; set; }
Expand Down
2 changes: 1 addition & 1 deletion testdata/Model/CSharp/Gitea/dat-skjema.cs
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ public class InnholdSkjema
public bool? BekreftRiktig { get; set; }

[RegularExpression(@"^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$")]
[XmlElement("AnsatteInnen", Order = 4)]
[XmlElement("AnsatteInnen", Order = 4, IsNullable = true)]
[JsonProperty("AnsatteInnen")]
[JsonPropertyName("AnsatteInnen")]
public string AnsatteInnen { get; set; }
Expand Down
12 changes: 6 additions & 6 deletions testdata/Model/CSharp/Gitea/nbib-melding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,32 +12,32 @@ namespace Altinn.App.Models
[XmlRoot(ElementName="Message")]
public class MessageV1
{
[XmlElement("ProcessTask", Order = 1)]
[XmlElement("ProcessTask", Order = 1, IsNullable = true)]
[JsonProperty("ProcessTask")]
[JsonPropertyName("ProcessTask")]
public string ProcessTask { get; set; }

[XmlElement("ServiceName", Order = 2)]
[XmlElement("ServiceName", Order = 2, IsNullable = true)]
[JsonProperty("ServiceName")]
[JsonPropertyName("ServiceName")]
public string ServiceName { get; set; }

[XmlElement("Title", Order = 3)]
[XmlElement("Title", Order = 3, IsNullable = true)]
[JsonProperty("Title")]
[JsonPropertyName("Title")]
public string Title { get; set; }

[XmlElement("Body", Order = 4)]
[XmlElement("Body", Order = 4, IsNullable = true)]
[JsonProperty("Body")]
[JsonPropertyName("Body")]
public string Body { get; set; }

[XmlElement("Reference", Order = 5)]
[XmlElement("Reference", Order = 5, IsNullable = true)]
[JsonProperty("Reference")]
[JsonPropertyName("Reference")]
public string Reference { get; set; }

[XmlElement("Sender", Order = 6)]
[XmlElement("Sender", Order = 6, IsNullable = true)]
[JsonProperty("Sender")]
[JsonPropertyName("Sender")]
public string Sender { get; set; }
Expand Down
2 changes: 1 addition & 1 deletion testdata/Model/CSharp/Gitea/skjema.cs
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ public class InnholdSkjema
public string SamfunnskritiskBransje { get; set; }

[RegularExpression(@"^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$")]
[XmlElement("BenyttesFraDato", Order = 15)]
[XmlElement("BenyttesFraDato", Order = 15, IsNullable = true)]
[JsonProperty("BenyttesFraDato")]
[JsonPropertyName("BenyttesFraDato")]
public string BenyttesFraDato { get; set; }
Expand Down
Loading

0 comments on commit 2664fed

Please sign in to comment.