Migrating from System.Runtime.Serialization to System.Text.Json

.NET Core 3.0 introduced namespace System.Text.Json which is meant to replace System.Runtime.Serialization and Newtonsoft.Json as the primary tool used when serializing and deserializing json.

If you have an older project you still might use System.Runtime.Serialization to serialize and deserialize json. In that case it is time to make the change to System.Text.Json. Here you will find a couple of things that we came by when we made the migration and which can be useful to know.

Controlling serialization with attributes

Let's use this class that uses System.Runtime.Serialization as an example:

// Using System.Runtime.Serialization
[Datacontract]
public class Request
{
    [DataMember(Name = "userName")]
    public string UserName { get; set; }

    [DataMember(Name = "orderReference", EmitDefaultValue = false)]
    public string? OrderReference { get; set; }
}

When using System.Text.Json you can no longer use the Datacontract and Datamember attributes. If you need to specify property name when serializing and deserializing you should instead use JsonPropertyName attribute.

Sometimes you want a value to be excluded from being serialized. EmitDefaultValue = false means that if a data member has its default value, then it will not be serialized. JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault) does the same in System.Text.Json. In this specific example it means that when OrderReference is null the property will not be serialized in to json.

The class above will now look like:

// Using System.Text.Json
public class Request
{
    [JsonPropertyName("userName")]
    public string UserName { get; set; }

    [JsonPropertyName("orderReference"), JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public string? OrderReference { get; set; }
}

Serializing objects

When serializing with System.Runtime.Serialization you have to first create an instance of DataContractJsonSerializer with the type which you want to use and after that use the WriteObject method to write the data to a memory stream. This data can then be encoded to a string.

// Using System.Runtime.Serialization
public static string SerializeWithSystemRuntime<T>(T value)
{
    using var stream = new MemoryStream();
    var serializer = new DataContractJsonSerializer(typeof(T));
    serializer.WriteObject(stream, value);
    var json = stream.ToArray();
    return Encoding.UTF8.GetString(json, 0, json.Length);
}

System.Text.Json has both JsonSerializer.Serialize and JsonSerializer.SerializeAsync methods which can be used to serialize. The latter one works in a similar way as DataContractJsonSerializer and writes the data to a stream.

JsonSerializer.Serialize is a bit simpler as it serializes the object directly to a string.

// Using System.Text.Json
public static string SerializeWithSystemText<T>(T value)
{
    return JsonSerializer.Serialize(value, value.GetType());
}

Specifying constructor

When using System.Text.Json and when the class has a public parameterized constructor, that constructor will be used to deserialize the class. If the class has multiple constructors then you need to use the JsonConstructor attribute to specify which constructor that will be used.

// Using System.Text.Json
public Request(string userName)
{
    UserName = userName;
}

[JsonConstructor]
public Request(string userName, string orderReference)
{
    UserName = userName;
    OrderNumber = orderNumber;
}

The advantage of System.Text.Json is its performance, it is much faster and it is also being improved continuously so making the change should not be in vain!

Author: Jonas Rönnqvist is a .NET student currently doing his internship at Active Solution working with Active Login.

Föregående
Föregående

Hemvändare på Active Solution

Nästa
Nästa

Går det att modernisera gamla system?