Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 43 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,50 @@
PM> Install-Package Shuttle.Core.Serialization
```

An implementation of the `ISerializer` interface is used to serialize objects into a `Stream`.
The following implementations of the `ISerializer` interface is used to serialize objects into a `Stream`:

The `DefaultSerializer` makes use of the standard .NET xml serialization functionality.
- `XmlSerializer` makes use of the standard .NET XML serialization functionality.
- `JsonSerializer` makes use of the `System.Test.Json` serialization functionality.

## Usage

### XmlSerializer

``` c#
services.AddXmlSerializer(builder => {
builder.Options = new XmlSerializerOptions
{
};

// or

buidler.Options.option = value;
});
```

The `builder.Options` contains properties that map to [XmlWriterSettings](https://learn.microsoft.com/en-us/dotnet/api/system.xml.xmlwritersettings?view=net-8.0) as well as [XmlDictionaryReaderQuotas](https://learn.microsoft.com/en-us/dotnet/api/system.xml.xmldictionaryreaderquotas?view=net-8.0).

### JsonSerializer

``` c#
services.AddJsonSerializer(builder => {
builder.Options = new JsonSerializerOptions
{
};

// or

buidler.Options.option = value;
});
```

The `builder.Options` is of type [JsonSerializerOptions](https://docs.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializeroptions?view=net-6.0).

## Methods

### Serialize

``` c#
Stream Serialize(object message);
Task<Stream> SerializeAsync(object message);
```

Expand All @@ -22,17 +56,16 @@ Returns the message `object` as a `Stream`.
### Deserialize

``` c#
object Deserialize(Type type, Stream stream);
Task<object> DeserializeAsync(Type type, Stream stream);
```

Deserializes the `Stream` into an `object` of the given type.

# ISerializerRootType
## ISerializerRootType

The `ISerializerRootType` interface is an optional interface that serializer implementations can use that allows the developer to specify explicit object types contained within a root type.
The `XmlSerializer` implements the `ISerializerRootType` interface which is an optional interface that serializer implementations can use that allows the developer to specify explicit object types contained within a root type.

The `DefaultSerializer` implements this interface and it is recommended that you explicitly register types with the same name, but in different namespaes, that will be serialized within the same root type to avoid any conflicts later down the line.
It is recommended that you explicitly register types with the same name, but in different namespaes, that will be serialized within the same root type to avoid any conflicts later down the line.

For instance, the following two types will cause issues when used in the root `Complex` type as they both serialize to the same name and the .Net serializer cannot seem to distinguish the difference:

Expand Down Expand Up @@ -63,12 +96,12 @@ namespace Serializer
}
```

By explicitly specifying the types the `DefaultSerializer` will add a namespace that will cause the types to be correctly identified.
By explicitly specifying the types the `XmlSerializer` will add a namespace that will cause the types to be correctly identified.

## AddSerializerType
### AddSerializerType

``` c#
void AddSerializerType(Type root, Type contained);
```

Specify the `contained` tpe that is used within te `root` type somewhere.
Specify the `contained` type that is used within the `root` type.
26 changes: 9 additions & 17 deletions Shuttle.Core.Serialization.Tests/ComplexSerializerType.cs
Original file line number Diff line number Diff line change
@@ -1,22 +1,14 @@
using System;
using Shuttle.Core.Serialization.Tests.v1;

namespace Shuttle.Core.Serialization.Tests
namespace Shuttle.Core.Serialization.Tests;

public class ComplexSerializerType
{
public class ComplexSerializerType
{
public ComplexSerializerType()
{
Id = Guid.NewGuid();
SomeSerializerType1 = new v1.SomeSerializerType();
AnotherSerializerType1 = new v1.AnotherSerializerType();
SomeSerializerType2 = new v2.SomeSerializerType();
AnotherSerializerType2 = new v2.AnotherSerializerType();
}
public AnotherSerializerType AnotherSerializerType1 { get; set; } = new();
public v2.AnotherSerializerType AnotherSerializerType2 { get; set; } = new();

public Guid Id { get; set; }
public v1.SomeSerializerType SomeSerializerType1 { get; set; }
public v1.AnotherSerializerType AnotherSerializerType1 { get; set; }
public v2.SomeSerializerType SomeSerializerType2 { get; set; }
public v2.AnotherSerializerType AnotherSerializerType2 { get; set; }
}
public Guid Id { get; set; } = Guid.NewGuid();
public SomeSerializerType SomeSerializerType1 { get; set; } = new();
public v2.SomeSerializerType SomeSerializerType2 { get; set; } = new();
}
102 changes: 0 additions & 102 deletions Shuttle.Core.Serialization.Tests/DefaultSerializerFixture.cs

This file was deleted.

64 changes: 64 additions & 0 deletions Shuttle.Core.Serialization.Tests/JsonSerializerFixture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using System;
using System.IO;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using NUnit.Framework;

namespace Shuttle.Core.Serialization.Tests
{
public class JsonSerializerFixture
{
[Test]
public async Task Should_be_able_to_serialize_and_deserialize_a_simple_type_async()
{
var original = new SimpleSerializerType();
var serializer = new JsonSerializer(Options.Create(new JsonSerializerOptions()));

var stream = await serializer.SerializeAsync(original);

stream.Position = 0;

var json = await new StreamReader(stream).ReadToEndAsync();

Assert.That(json.Contains(original.Id.ToString()), Is.True);

stream.Position = 0;

Assert.That(((SimpleSerializerType)await serializer.DeserializeAsync(typeof(SimpleSerializerType), stream)).Id, Is.EqualTo(original.Id));
}

[Test]
public async Task Should_be_able_to_serialize_and_deserialize_a_complex_type_async()
{
var complex = new ComplexSerializerType();
var serializer = new JsonSerializer(Options.Create(new JsonSerializerOptions()));

var stream = await serializer.SerializeAsync(complex);

stream.Position = 0;

var json = await new StreamReader(stream).ReadToEndAsync();

Assert.That(json.Contains(complex.Id.ToString()), Is.True);

stream.Position = 0;

Assert.That(((ComplexSerializerType)await serializer.DeserializeAsync(typeof(ComplexSerializerType), stream)).Id, Is.EqualTo(complex.Id));

Console.WriteLine(json);

var some1 = new v1.SomeSerializerType();
var some2 = new v2.SomeSerializerType();

var some1Serialized = await serializer.SerializeAsync(some1);
var some2Serialized = await serializer.SerializeAsync(some2);

some1Serialized.Position = 0;
some2Serialized.Position = 0;

Assert.That(((v1.SomeSerializerType)await serializer.DeserializeAsync(typeof(v1.SomeSerializerType), some1Serialized)).Id, Is.EqualTo(some1.Id));
Assert.That(((v2.SomeSerializerType)await serializer.DeserializeAsync(typeof(v2.SomeSerializerType), some2Serialized)).Id, Is.EqualTo(some2.Id));
}
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net6.0</TargetFrameworks>
<TargetFrameworks>net8.0</TargetFrameworks>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="NUnit" Version="3.14.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageReference Include="NUnit" Version="4.2.2" />
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Shuttle.Core.Serialization\Shuttle.Core.Serialization.csproj" />
</ItemGroup>

</Project>
</Project>
2 changes: 1 addition & 1 deletion Shuttle.Core.Serialization.Tests/SimpleSerializerType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ namespace Shuttle.Core.Serialization.Tests
{
public class SimpleSerializerType
{
public Guid Id { get; set; }
public Guid Id { get; set; } = Guid.NewGuid();
}
}
57 changes: 57 additions & 0 deletions Shuttle.Core.Serialization.Tests/XmlSerializerFixture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using NUnit.Framework;

namespace Shuttle.Core.Serialization.Tests
{
public class XmlSerializerFixture
{
[Test]
public async Task Should_be_able_to_serialize_and_deserialize_a_simple_type_async()
{
var original = new SimpleSerializerType();
var serializer = new XmlSerializer(Options.Create(new XmlSerializerOptions()));

var stream = await serializer.SerializeAsync(original);

var xml = await new StreamReader(stream).ReadToEndAsync();

Assert.That(xml.Contains(original.Id.ToString()), Is.True);

stream.Position = 0;

Assert.That(((SimpleSerializerType)await serializer.DeserializeAsync(typeof(SimpleSerializerType), stream)).Id, Is.EqualTo(original.Id));
}

[Test]
public async Task Should_be_able_to_serialize_and_deserialize_a_complex_type_async()
{
var complex = new ComplexSerializerType();
var serializer = new XmlSerializer(Options.Create(new XmlSerializerOptions()));

serializer.AddSerializerType(typeof(ComplexSerializerType), typeof(v1.SomeSerializerType));
serializer.AddSerializerType(typeof(ComplexSerializerType), typeof(v1.AnotherSerializerType));
serializer.AddSerializerType(typeof(ComplexSerializerType), typeof(v2.SomeSerializerType));
serializer.AddSerializerType(typeof(ComplexSerializerType), typeof(v2.AnotherSerializerType));

var stream = await serializer.SerializeAsync(complex);
var xml = await new StreamReader(stream).ReadToEndAsync();

Assert.That(xml.Contains(complex.Id.ToString()), Is.True);

stream.Position = 0;

Assert.That(((ComplexSerializerType)await serializer.DeserializeAsync(typeof(ComplexSerializerType), stream)).Id, Is.EqualTo(complex.Id));

Console.WriteLine(xml);

var some1 = new v1.SomeSerializerType();
var some2 = new v2.SomeSerializerType();

Assert.That(((v1.SomeSerializerType)await serializer.DeserializeAsync(typeof(v1.SomeSerializerType), await serializer.SerializeAsync(some1))).Id, Is.EqualTo(some1.Id));
Assert.That(((v2.SomeSerializerType)await serializer.DeserializeAsync(typeof(v2.SomeSerializerType), await serializer.SerializeAsync(some2))).Id, Is.EqualTo(some2.Id));
}
}
}
Loading