In many applications, we often work with data that looks different but shares some common features. For example, a system might have different types of records or transactions that have similar properties but also their own unique details. Handling this kind of data can be tricky when saving or loading it as JSON.
We already know polymorphism lets us treat different types of objects as a single base type. Polymorphic serialization in .NET 7 makes it easy to work with different types of data that share common properties. With JsonPolymorphic and JsonDerivedType in System.Text.Json, you can save and load objects with a base class while keeping the unique details of each type.
In this article, I will talk about how JSON polymorphic serialization works and how we applied it to manage patient records in a Cardiology Practice Management System.
Let's look at the code:
Base type for patient records
[JsonPolymorphic(TypeDiscriminatorPropertyName = "recordType")]
[JsonDerivedType(typeof(ECGRecord), typeDiscriminator: "ECG")]
[JsonDerivedType(typeof(EchoCardiogramRecord), typeDiscriminator: "EchoCardiogram")]
[JsonDerivedType(typeof(CardiacEventRecord), typeDiscriminator: "CardiacEvent")]
[JsonDerivedType(typeof(ConsultationRecord), typeDiscriminator: "Consultation")]
public abstract class PatientRecordBase;
Other derived types
Each type of patient record inherits from PatientRecordBase and adds its own unique fields.
public class ECGRecord : PatientRecordBase
{
public int HeartRate { get; set; }
public RhytmType RhythmType { get; set; }
}
public class EchoCardiogramRecord : PatientRecordBase
{
public double EjectionFraction { get; set; }
public string Observations { get; set; }
.....
}
public class CardiacEventRecord : PatientRecordBase
{
public string EventDescription { get; set; }
public string Trigger { get; set; }
public string Outcome { get; set; }
.....
}
public class ConsultationRecord : PatientRecordBase
{
public string DoctorNotes { get; set; }
//we use same approach for prescriptions as well.
//Doctor may prescribe different things,right?
// such as : pharmaceutical drugs,Lifestylechanges,advices,tests
public List<PrescriptionBase> Prescriptions { get; set; }
.....
}
Patient Records API
public class PatientRecordCreateRequest
{
public string PatientId { get; set; }
public DateTimeOffset DateTime { get; set; }
public RecordType RecordType { get; set; }
public PatientRecordBase Record { get; set; }
}
[Route("api/{patients}")]
[Authorize]
public class PatientRecordsController(IPatientService service, IMapper mapper) : ControllerBase
{
[HttpPost]
public async Task<IActionResult> CreateAsync([FromBody] PatientRecordCreateRequest request)
{
// PatientRecord structure is same as PatientRecordCreateRequest
var patient = await service.CreateAsync(mapper.Map<PatientRecord>(request));
return Ok(patient);
}
}
Let's see in action
Request payload
{
"patientId": "p-7415879",
"dateTime": "2024-11-30T06:07:44.390Z",
"records": [
{
"recordType": "ECG",
"heartRate": 72,
"rhythmType": "Sinus"
},
{
"recordType": "EchoCardiogram",
"ejectionFraction": 55.6,
"observations": "Normal function"
},
{
"recordType": "Consultation",
"doctorNotes": "Tachycardia during workout... "
}
]
}
Thanks for reading!
Top comments (0)