JsonConverter equivalent in using System.Text.Json
Asked Answered
F

2

46

I'm starting to migrate some code I have from Newtonsoft.Json to System.Text.Json in a .net Core 3.0 app.

I migrated the properties from

[JsonProperty("id")] to [JsonPropertyName("id")]

but I have some properties decorated with the JsonConverter attribute as:

[JsonConverter(typeof(DateTimeConverter))] [JsonPropertyName("birth_date")] DateTime BirthDate{ get; set; }

But I cannot find the equivalent of this Newtonsoft converter in System.Text.Json Does someone know how can this be achieved in .net Core 3.0?

Thanks!

Facelifting answered 29/5, 2019 at 12:15 Comment(3)
Wouldn't it be easier to use Newtonsoft instead rather than migrating it all over?Triciatrick
That's another question, but I'd like to know if this can be achieved in System.Text.JsonFacelifting
Not sure the new JSON objects are mature enough to cope with all circumstances right now, but happy to be proven wrong. Making .NET Core 3 use Newtonsoft though, is a one line change I believe.Triciatrick
T
47

System.Text.Json now supports custom type converters in .NET 3.0 preview-7 and above.

You can add converters that match on type, and use the JsonConverter attribute to use a specific converter for a property.

Here's an example to convert between long and string (because javascript doesn't support 64-bit integers).

public class LongToStringConverter : JsonConverter<long>
{
    public override long Read(ref Utf8JsonReader reader, Type type, JsonSerializerOptions options)
    {
        if (reader.TokenType == JsonTokenType.String)
        {
            // try to parse number directly from bytes
            ReadOnlySpan<byte> span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan;
            if (Utf8Parser.TryParse(span, out long number, out int bytesConsumed) && span.Length == bytesConsumed)
                return number;

            // try to parse from a string if the above failed, this covers cases with other escaped/UTF characters
            if (Int64.TryParse(reader.GetString(), out number))
                return number;
        }

        // fallback to default handling
        return reader.GetInt64();
    }

    public override void Write(Utf8JsonWriter writer, long value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(value.ToString());
    }
}

Then apply to your property as follows:

// Be sure not to use Newtonsoft.Json which also has a JsonConverter attribute
using System.Text.Json.Serialization;

public class Model
{
    [JsonConverter(typeof(LongToStringConverter))]
    public long MyProperty { get; set; }
}

Or register the converter by adding it to the Converters list in JsonSerializerOptions

services.AddControllers().AddJsonOptions(options =>
{
    options.JsonSerializerOptions.Converters.Add(new LongToStringConverter());
});

Note: in .NET 5 and later, to make your converter handle null values override HandleNull and return true. In .NET Core 3 this was not possible.

Tendon answered 3/8, 2019 at 1:24 Comment(4)
Just for reference: If someone is searching for StringEnumConverter in System.Text.Json: using System.Text.Json.Serialization; [JsonConverter(typeof(JsonStringEnumConverter))]. Check learn.microsoft.com/en-us/dotnet/api/….Nominalism
How do I convert to a custom type? {x: {foo:1,bar:2,baz:{apple:1,orange:2, juice:[1,2,3,4,5]}}Testy
@Testy You create your type then write a converter that inherits from JsonConverter<YourType> with the read and write logic you need. The documentation has lots of samples that show you how to interact with the API: learn.microsoft.com/en-us/dotnet/standard/serialization/…Tendon
@Nominalism It does serialize, but it does not respect the EnumMember attribute value and thus the Enum name is serialized instead System.Text.Json: JsonStringEnumConverter ignores its JsonNamingPolicy during deserialization. #31619Cosgrove
V
4

You can find the JsonConverterAttribute in the namespace System.Text.Json.Serialization.

https://learn.microsoft.com/en-us/dotnet/api/system.text.json.serialization.jsonconverterattribute?view=netcore-3.0

Vizard answered 25/9, 2019 at 19:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.