4

I have two classes in .Net Core

The class Ownership

namespace CustomStoreDatabase.Models
{
    public class Ownership
    {
        public string OwnershipId { get; set; }
        public List<string> TextOutput { get; set; }
        public DateTime DateTime { get; set; }
        public TimeSpan MeanInterval { get; set; }// Like long ticks, TimeSpan.FromTicks(Int64), TimeSpan.Ticks
    }
}

I need to show MeanInterval like long ticks, using the methods TimeSpan.FromTicks(Int64) and TimeSpan.Ticks.

My custom JsonConverter

using CustomStoreDatabase.Models;
using System;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace CustomStoreDatabase.Util
{
    public class OwnershipJSonConverter : JsonConverter<Ownership>
    {
        public override bool CanConvert(Type typeToConvert)
        {
            return true;
        }

        public override Ownership Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            if (reader.TokenType != JsonTokenType.StartObject)
            {
                throw new JsonException();
            }
            //*******************
            // HOW TO IMPLEMENT?
            //*******************
            //throw new NotImplementedException();
        }

        public override void Write(Utf8JsonWriter writer, Ownership value, JsonSerializerOptions options)
        {
            writer.WriteStartObject();
            if (value != null)
            {
                writer.WriteString("OwnershipId", value.OwnershipId);
                writer.WriteString("TextOutput", JsonSerializer.Serialize(value.TextOutput));
                writer.WriteString("DateTime", JsonSerializer.Serialize(value.DateTime));
                if (value.MeanInterval != null)
                {
                    writer.WriteNumber("MeanInterval", (long)value.MeanInterval.Ticks);
                }
                else
                {
                    writer.WriteNull("MeanInterval");
                }
            }
            writer.WriteEndObject();
        }
    }
}

I don't know how to implement the Read method. How can I implement the custom Deserialization overriding the Read method?

If is possible you guys proposal to me another implementation for CanConvert method, I thank you very much.

ProgrammingLlama
  • 36,677
  • 7
  • 67
  • 86
  • Can you modify your `Ownership` model to add `System.Text.Json` attributes, or is the model effectively read-only for the purposes of this question? – dbc Feb 06 '21 at 16:35
  • @dbc Preferably it is better not to modify the class, because for one use I have to get a JSON format, for another use another JSON format. If I change the class to set a single JSON format, it couldn't set the other JSON format. –  Feb 07 '21 at 18:29

1 Answers1

5

It seems like you only want to perform custom serialization of TimeSpan as it belongs to Ownership, so why not make a converter for TimeSpan only and save yourself from manually serializing all of the other class properties?:

public class TimeSpanConverter : JsonConverter<TimeSpan>
{
    public override TimeSpan Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        return TimeSpan.FromTicks(reader.GetInt64());
    }

    public override void Write(Utf8JsonWriter writer, TimeSpan value, JsonSerializerOptions options)
    {
        writer.WriteNumberValue(value.Ticks);
    }
}

Then decorate your MeanInterval property with a JsonConverterAttribute:

public class Ownership
{
    public string OwnershipId { get; set; }
    public List<string> TextOutput { get; set; }
    public DateTime DateTime { get; set; }
    [JsonConverter(typeof(TimeSpanConverter))]
    public TimeSpan MeanInterval { get; set; }// Like long ticks, TimeSpan.FromTicks(Int64), TimeSpan.Ticks
}

Try it online

ProgrammingLlama
  • 36,677
  • 7
  • 67
  • 86
  • Hi, John, Thanks´a lot!, Great answer. But unfortunately I removed another class with `TimeSpan` property, https://stackoverflow.com/q/66072157/5113188,I need to apply it specifically as a property of the `Ownership` class, because another `Owner` class has another property of `TimeSpan`. Checking the System.Text.Json.Serialization.Json `JsonConverter` class only contains `CanConvert`, `Read` and `Write` methods.. –  Feb 06 '21 at 06:11
  • @QA_Col See [this fiddle](https://dotnetfiddle.net/QKTRqk) for an updated example of how this works when you use it. You can see that only properties with the attribute applied are affected by the converter. I've also corrected my answer to System.Text.Json instead of Json.NET (my mistake before, sorry). – ProgrammingLlama Feb 06 '21 at 06:30