How to deserialize java duration in c#?

163 Views Asked by At

Assuming that I got a duration from Java: "PT-328H-46M-43.2082074S". How to deserialize it to NodaTime Duration in system.text.json?

1

There are 1 best solutions below

0
Jon Skeet On BEST ANSWER

That's the format that Noda Time usually uses for periods rather than durations. Unfortunately the presence of multiple signs within the value means you can't parse it using DurationPattern - but PeriodPattern.NormalizingIso appears to work okay:


using NodaTime.Text;

var pattern = PeriodPattern.NormalizingIso;
var result = pattern.Parse("PT-328H-46M-43.2082074S");
var period = result.Value;
var duration = period.ToDuration();

Console.WriteLine(duration);

To use that within System.Text.Json, you'd need to specify the right period pattern... and then potentially sort of "trampoline" from the period to the duration. Here's a complete example:

Program.cs:

using NodaTime;
using NodaTime.Serialization.SystemTextJson;
using NodaTime.Text;
using System.Text.Json;

string json = """
{
  "name": "Jon",
  "duration": "PT-328H-46M-43.2082074S"
}
""";

var settings = new NodaJsonSettings
{
    PeriodConverter = new NodaPatternConverter<Period>(PeriodPattern.NormalizingIso)
};
var options = new JsonSerializerOptions().ConfigureForNodaTime(settings);

var model = JsonSerializer.Deserialize<Model>(json, options);
Console.WriteLine(model.Duration);

Model.cs:

using NodaTime;
using System.Text.Json.Serialization;

public class Model
{
    [JsonPropertyName("name")]
    public string Name { get; set; }

    [Obsolete]
    [JsonPropertyName("duration")]
    public Period Period
    {
        // TODO: A getter, if you want to be able to serialize back.
        // That's a little more work as there isn't a Duration.ToPeriod conversion.
        set => Duration = value.ToDuration();
    }

    [JsonIgnore]
    public Duration Duration { get; set; }
}