DEV Community

Galina Melnik
Galina Melnik

Posted on • Edited on

3 2

JsonConverter<T>

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);
Enter fullscreen mode Exit fullscreen mode

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; }
    }
Enter fullscreen mode Exit fullscreen mode

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();
        }
    }
Enter fullscreen mode Exit fullscreen mode

I don't need to serialize the object. That's why I don't write code for Write method by now.

Sentry image

Hands-on debugging session: instrument, monitor, and fix

Join Lazar for a hands-on session where you’ll build it, break it, debug it, and fix it. You’ll set up Sentry, track errors, use Session Replay and Tracing, and leverage some good ol’ AI to find and fix issues fast.

RSVP here →

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay