1
votes

Let's say I have an object of type MyClass that is serialized to Json as follows:

{"DurationField":"3 Months", *OtherProperties*}

I want to deserialize this Json into the following class:

public class MyClass{
  *OTHER PROPERTIES*

  public Duration DurationField{ get; set;}
}

public class Duration{
  public Duration()

  // Constructor that takes a string, parses it and sets Units and N
  public Duration(string strValue){
  Duration duration = Duration.Parse(strValue)
  N = duration.N;
  Units = duration.Units;
}

  // private method that takes a string and returns a Duration
  private Duration Parse(string str){
   ...
}

  // Enum field to represent units of time, like day/month/year
  public TimeUnits Units{ get; set;}

  // Number of units of time
  public int N{ get; set;}

}

I've tried to implement a custom JsonConverter (below), only to realize that it would only work on a child node of "DurationField", meaning that I would have to make it serialize to "DurationField":{ "Value": "3 Months"} or something similar.

public sealed class DurationConverter : JsonConverter<Duration>
  {
    public override bool CanConvert(Type objectType)
    {
      return (objectType == typeof(Duration));
    }

    public override Duration Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
      // Load the JSON for the Result into a JObject
      JObject jo = JObject.Parse(reader.GetString());

      // Read the properties which will be used as constructor parameters
      string durationString = (string)jo["DurationField"];

      // Construct the Result object using the non-default constructor
      Duration result = new Duration(tenorString);

      // (If anything else needs to be populated on the result object, do that here)

      // Return the result
      return result;
    }


    public override void Write(Utf8JsonWriter writer, Duration value, JsonSerializerOptions options)
    {
      JsonSerializer.Serialize(writer, value, options);
    }
  }

Is there any way around this? I.e., make the Custom converter take a string as input and convert it to an object after parsing the string? The closest thing that I can think of is JsonStringEnumConverter, which takes a string and turns it into an Enum.

1
Why do you mix Newtonsoft.JSON and System.Text.Json APIs?Pavel Anikhouski

1 Answers

0
votes

I know this is not so much what you asked for, but one way around this might be:

public class MyClass{
  *OTHER PROPERTIES*

  public string DurationField { get; set;}
  private Duration _duration = null;

  [JsonIgnore]
  public Duration Duration {
    get {
      if (_duration == null) {
        _duration = new Duration(this.DurationField);
      }

      return _duration;
    }
  }
}

Which allows you to preserve string value raw in case it is unparseable correctly etc, but also gives you access to your Duration.