JsonConverter&lt;T&gt;
Tags: csharp, dotnet
Published: 2021-02-28 11:58:28

I want to create home pet project with Mars wheather. Thanks God NASA have a public API with data.
Test URL https://api.nasa.gov/insight_weather/?api_key=DEMO_KEY&feedtype=json&ver=1.0 
And there is their json for today :
`{
  "782": {
    "First_UTC": "2021-02-06T17:08:11Z", 
    "Last_UTC": "2021-02-07T17:47:46Z", 
    "Month_ordinal": 12, 
    "Northern_season": "late winter", 
    "PRE": {
      "av": 721.77, 
      "ct": 113450, 
      "mn": 698.8193, 
      "mx": 742.2686
    }, 
    "Season": "winter", 
    "Southern_season": "late summer", 
    "WD": {
      "most_common": null
    }
  }, 
  "783": {
    "First_UTC": "2021-02-07T17:47:46Z", 
    "Last_UTC": "2021-02-08T18:27:22Z", 
    "Month_ordinal": 12, 
    "Northern_season": "late winter", 
    "PRE": {
      "av": 722.186, 
      "ct": 107270, 
      "mn": 698.7664, 
      "mx": 743.1983
    }, 
    "Season": "winter", 
    "Southern_season": "late summer", 
    "WD": {
      "most_common": null
    }
  }, ... irrelevant
"sol_keys": [... irrelevant],
"validity_checks": { ...irrelevant }
}`

I've created a project using netcoreapp3.0 and wanted to use System.Text.Json library. My first wrong way to do it was : 
```
var dict = await JsonSerializer.DeserializeAsync<Dictionary<string, MarsWheather>>(stream);
```
But I caught an exception 
`
System.Text.Json.JsonException: The JSON value could not be converted to MarsWheather. Path: $.sol_keys | LineNumber: 120 | BytePositionInLine: 15.`
BOOM!
That's why I've created custom JsonConverter. I hope this code will helpful for community.
UPDATE 03/03/2021 : There was a bug with my code. This is a new version without it.
Data classes is :
```
[JsonConverter(typeof(MarsWheatherRootObjectConverter))]
    public class MarsWheatherRootObject
    {
        public List<MarsWheather> MarsWheather { get; set}
    }
    public class MarsWheather {
        public int Sol { get; set; }
        [JsonPropertyName("First_UTC")]
        public DateTime FirstUTC { get; set; }
        [JsonPropertyName("Last_UTC")]
        public DateTime LastUTC { get; set; }
        [JsonPropertyName("Season")]
        [JsonConverter(typeof(JsonStringEnumConverter))]
        public Season MarsSeason { get; set; }
        [JsonPropertyName("PRE")]
        public DataDescription AtmosphericPressure { get; set; }
    }
```
I've created an class wrapper (MarsWheatherRootObject) to use class attribute.
```
internal class MarsWheatherRootObjectConverter : JsonConverter<MarsWheatherRootObject>
    {
        public override MarsWheatherRootObject Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            var root = new MarsWheatherRootObject();
            var list = new List<MarsWheather>();
            while (reader.Read())
            {
                switch (reader.TokenType)
                {
                    case JsonTokenType.PropertyName:
                    case JsonTokenType.String:
                        var keyStr = reader.GetString();
                        int key;
                        if (!int.TryParse(keyStr, out key))
                        {
                            reader.Skip();
                        }
                        else
                        {
                            var value = JsonSerializer.Deserialize<MarsWheather>(ref reader, options);
                            value.Sol = key;
                            list.Add(value);
                        }
                        break;
                    default: break;
                }
            }
            root.MarsWheather = list;
            return root;
        }

        public override void Write(Utf8JsonWriter writer, MarsWheatherRootObject value, JsonSerializerOptions options)
        {
            throw new NotImplementedException();
        }
    }
```
I don't need to serialize the object. That's why I don't write code for Write method by now.