Issue
First off, I had a hard time with the title of this one; I'll edit it if I get any better suggestions.
I have a json string that looks like this
{
"chapters": [
{
"id": 0,
"tags": {
"title": "Chapter 1"
}
},
{
"id": 1,
"tags": {
"title": "Chapter 2"
}
}
]
}
My model for this is as such
public class Chapter
{
[JsonPropertyName("id")]
public int Id { get; set; }
[JsonPropertyName("tags")]
public ChapterTags Tags { get; set; }
[JsonIgnore]
public string Title
{
get { return Tags.Title; }
set { if (Tags.Title != value) Tags.Title = value; }
}
}
public class ChapterTags
{
[JsonPropertyName("title")]
public string Title { get; set; }
}
and here is the code I'm using to deserialize the json
var jsonTask = GetJsonAsync();
using var jsonResults = JsonDocument.Parse(await jsonTask);
var jsonChapters = jsonResults.RootElement.GetProperty("chapters");
List<Chapter> chapters = JsonSerializer.Deserialize<List<Chapter>>(jsonChapters) ?? new();
I want to get rid of the Tags
property and the ChapterTags
class and just be left with
public class Chapter
{
[JsonPropertyName("id")]
public int Id { get; set; }
public string Title {get; set;}
}
as a simple single class model.
My only thought was to use a JsonConverter but could not figure out how to make that work. I can't change the format of the json input because it is being generated by an outside source.
Also, if it matters, I will never have to re-serialize the object back to json.
I am using VS2022 Preview, as that is currently the only way to work with .Net Maui.
Solution
I ended up going the converter route.
Recap of input JSON
{
"chapters": [
{
"id": 0,
"tags": {
"title": "Chapter 1"
}
},
{
"id": 1,
"tags": {
"title": "Chapter 2"
}
}
]
}
My converter class
public class JsonChapterTitleConverter : JsonConverter<string>
{
public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
using var jsonTags = JsonDocument.ParseValue(ref reader);
var jsonTitle = jsonTags.RootElement.GetProperty("title");
return jsonTitle.GetString();
}
public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options) => throw new NotImplementedException();
}
New model
public class Chapter
{
[JsonPropertyName("id")]
public int Id { get; set; }
[JsonPropertyName("tags")]
[JsonConverter(typeof(JsonChapterTitleConverter))]
public string Title { get; set; }
}
The code used to deserialize the JSON is unchanged
I like the answer Serge gave. In this case however, I feel like it violates the Open-Closed Principle (if I understand it correctly). The JSON shown is not the full string; only what is important to me at the moment. If I decide I need to deserialize more of the elements; not only would I have to extend my model, but also modify the deserialization method in my service class. Using the converter means I only have to add another property to my model corresponding to the JSON property I want to capture.
While Maksym's answer isn't a complete answer, the link provided gave me the boost I needed to figure this out.
Thank you.
Comments welcome.
Answered By - master_ruko Answer Checked By - Dawn Plyler (PHPFixing Volunteer)
0 Comments:
Post a Comment
Note: Only a member of this blog may post a comment.