using System.Reflection; using adas_core.Domain.Models; using adas_core.Domain.Models.Pumps; using MongoDB.Bson.Serialization; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Linq; using JsonConverterAttribute = Newtonsoft.Json.JsonConverterAttribute; namespace adas_core.Infrastructure.Utils; /// /// Provides JSON conversion for instances and supports BSON serialization through the interface. /// public class PatientPumpObservationConverter : JsonConverter, IBsonSerializer { /// /// Deserializes a BSON value into a .NET object using the provided deserialization context and arguments. /// /// The BSON deserialization context that provides access to the reader and configuration. /// The deserialization arguments containing additional settings for the operation. /// The deserialized object. /// Thrown when the method is invoked, as the deserialization logic has not been implemented. public object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) { throw new NotImplementedException(); } /// /// Serializes the specified value into BSON format using the provided serialization context and arguments. /// This method is not yet implemented and currently throws an exception when invoked. /// /// The BSON serialization context that provides the writer and configuration for the operation. /// The BSON serialization arguments that influence the serialization behavior. /// The object to be serialized into BSON. /// Thrown because the method has not been implemented. public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value) { throw new NotImplementedException(); } public Type ValueType => typeof(PatientObservationAlarm); /// /// Deserializes a JSON representation into a instance. /// This implementation is not yet provided and always throws an exception. /// /// The to read JSON from. /// The type of the object to deserialize. /// The existing value of the object being read, or null if there is no existing value. /// A value indicating whether has a value. /// The used for deserialization. /// A instance reconstructed from the JSON data. /// Thrown because the method has not been implemented yet. public override PumpObservation ReadJson(JsonReader reader, Type objectType, PumpObservation? existingValue, bool hasExistingValue, JsonSerializer serializer) { throw new NotImplementedException(); } /// /// Serializes the specified value to JSON, applying string enum conversion to the Event, Status, PumpMode, InfusingStatus, and AlarmMode properties. No output is written when the value is null. /// /// The JSON writer to which the serialized object is written. /// The object to serialize; if null, the method does nothing. /// The JSON serializer used as context for the conversion. public new void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { if (value != null) { var jo = JObject.FromObject(value); // Add [JsonConverter(typeof(StringEnumConverter))] attribute to specified properties AddStringEnumConverterAttribute(value, "Event"); AddStringEnumConverterAttribute(value, "Status"); AddStringEnumConverterAttribute(value, "PumpMode"); AddStringEnumConverterAttribute(value, "InfusingStatus"); AddStringEnumConverterAttribute(value, "AlarmMode"); jo.WriteTo(writer); } } /// /// Serializes a instance to JSON. This override is not yet implemented and will always throw. /// /// The JSON writer used to emit the serialized output. /// The to serialize, or if no value is available. /// The providing serialization context and options. /// Always thrown because the method has not been implemented. public override void WriteJson(JsonWriter writer, PumpObservation? value, JsonSerializer serializer) { throw new NotImplementedException(); } /// /// Adds a of type to the specified property, ensuring that enum values are serialized as their string names rather than numeric values. If the property already has a applied, no changes are made. /// /// The object instance whose property will be inspected for the attribute. /// The name of the property to which the converter attribute will be added. private static void AddStringEnumConverterAttribute(object value, string propertyName) { var prop = value.GetType().GetProperty(propertyName); var attr = new JsonConverterAttribute(typeof(StringEnumConverter)); if (prop != null) { var attrs = prop.GetCustomAttributes(false); // Check if the attribute is not already applied if (Array.Find(attrs, a => a is JsonConverterAttribute) == null) { // Create a new array that includes the existing attributes and the new one var newAttrs = new object[attrs.Length + 1]; Array.Copy(attrs, newAttrs, attrs.Length); newAttrs[attrs.Length] = attr; // Use reflection to set the new attributes array var field = typeof(PropertyInfo).GetField("m_customAttributes", BindingFlags.Instance | BindingFlags.NonPublic); field?.SetValue(prop, newAttrs); } } } } /*How to use it: BsonSerializer.RegisterSerializer(new PatientObservationAlarmConverter()); JsonConvert.DefaultSettings = () => new JsonSerializerSettings { Converters = { new PatientObservationAlarmConverter() } }; */