'How to remove a middle property from JSON in System.Text.Json?

Let's say we have these C# classes:

public class Teacher
{
    public long Id { get; set; }
    public string Name { get; set; }
    public boolean IsActive { get; set; }
    public dynamic RelatedItems { get; set; }
}
public class Student
{
    public long Id { get; set; }
    public string Name { get; set; }
    public double AverageScrore { get; set; }
    public dynamic RelatedItems { get; set; }
}
public class Course
{
    public long Id { get; set; }
    public string Title { get; set; }
}

And here's the object graph that is built:

var teacher = teacherService.Get(teacherId);
teacher.RelatedItems.Students = studentService.GetByTeacherId(teacherId);
foreach (var student in teacher.RelatedItems.Students)
{
    student.RelatedItems.Courses = courseService.GetStudentCourses(studentId);
}

The object graph above produces this JSON after serialization (using System.Text.Json):

{
    "Id": "5",
    "Name": "John",
    "IsActive": true,
    "RelatedItems": {
        "Students": [
            {
                "Id": 7,
                "Name": "Joe",
                "AverageScore": 9.3,
                "RelatedItems": {
                    "Courses": [
                        {
                            "Id": 12,
                            "Title": "Math"
                        }
                    ]
                }
            }
        ]
    }
}

What I need to do is to remove those RelatedItems in the serialized JSON, and move their children one step up. This would be the result:

{
    "Id": "5",
    "Name": "John",
    "IsActive": true,
    "Students": [
        {
            "Id": 7,
            "Name": "Joe",
            "AverageScore": 9.3,
            "Courses": [
                {
                    "Id": 12,
                    "Title": "Math"
                }
            ]
        }
    ]
}

Is it possible to be done via System.Text.Json?



Solution 1:[1]

You have to write custom classes for serialization

var options = new JsonSerializerOptions();
options.Converters.Add(new CustomJsonConverter());
json = JsonSerializer.Serialize(StudentClassObject, options);

Implementation of CustomJsonConverter

public class CustomJsonConverter : JsonConverter<Student>
{
    public override Book Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        // Use default implementation when deserializing (reading)
        return JsonSerializer.Deserialize<Book>(ref reader, options);
    }

    public override void Write(Utf8JsonWriter writer, Book value, JsonSerializerOptions options)
    {
        writer.WriteStartObject();

        using (JsonDocument document = JsonDocument.Parse(JsonSerializer.Serialize(value)))
        {
            foreach (var property in document.RootElement.EnumerateObject())
            {
                if (property.Name != "RelatedItems")
                    property.WriteTo(writer);
            }
        }

        writer.WriteEndObject();
    }    

}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Ajay Gupta