using System.Reflection; using adas_core.Domain.Models; using MongoDB.Bson.Serialization; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Linq; namespace adas_core.Infrastructure.Utils; /// /// Converts instances to and from JSON representation. /// /// /// Implements to provide BSON serialization and deserialization support for objects. /// public class PatientObservationAlarmConverter : JsonConverter, IBsonSerializer { /// /// Deserializes a BSON value into a .NET object using the supplied deserialization context and arguments. /// /// The BSON deserialization context that provides access to the reader and configuration. /// The deserialization arguments that influence how the value is read and converted. /// The deserialized .NET object produced from the BSON input. /// Always thrown because the deserialization logic has not been implemented yet. public object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) { throw new NotImplementedException(); } /// /// Serializes the specified value to BSON format using the provided serialization context and arguments. /// /// The BSON serialization context that holds the writer and configuration for the serialization operation. /// The BSON serialization arguments containing additional information that influences the serialization behavior. /// The object to be serialized into BSON. /// Thrown because the method has not yet been implemented. public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value) { throw new NotImplementedException(); } public Type ValueType => typeof(PatientObservationAlarm); /// /// Deserializes a JSON token into a instance. Returns null when the JSON token is , otherwise extracts the value property from the JSON object and constructs a new alarm, falling back to a default when the value is missing. /// /// The positioned at the JSON token to read. /// The type of the object being deserialized. /// The existing value of the object being deserialized, or null if none exists. /// Indicates whether contains a value to be used during deserialization. /// The used for nested object deserialization. /// A populated from the JSON, or null if the JSON token is . public override PatientObservationAlarm? ReadJson(JsonReader reader, Type objectType, PatientObservationAlarm? existingValue, bool hasExistingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) return null; // Implement your custom deserialization logic here var jsonObject = JObject.Load(reader); // Deserialize properties from jsonObject to PatientObservationAlarm object // Example: Deserialize 'Value' property var value = jsonObject.GetValue("value")?.ToObject(); return new PatientObservationAlarm { Value = value ?? new object() // Other property assignments... }; } /// /// Serializes the specified object to JSON, applying the to the eventPhase, state, priority, and type properties, while excluding the messageTime and expired properties from the output. Does nothing when the is . /// /// The to which the JSON output is written. /// The object to serialize; if , the method performs no action. /// The used to assist with 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, "eventPhase"); AddStringEnumConverterAttribute(value, "state"); AddStringEnumConverterAttribute(value, "priority"); AddStringEnumConverterAttribute(value, "type"); jo.Property("messageTime")?.Remove(); jo.Property("expired")?.Remove(); jo.WriteTo(writer); } } /// /// Adds a JSON converter attribute to the specified property of the given object, if one is not already present. Uses reflection to inject the attribute into the property's internal custom attributes array, avoiding the need to recompile the type with the attribute applied. /// /// The object instance whose type is inspected to locate the target property. /// The name of the property to which the 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); } } } /// /// Writes the JSON representation of a PatientObservationAlarm using the specified writer and serializer. /// /// The JsonWriter to which the JSON output is written. /// The PatientObservationAlarm value to serialize. /// The JsonSerializer used during the serialization process. /// The method has not been implemented. public override void WriteJson(JsonWriter writer, PatientObservationAlarm? value, JsonSerializer serializer) { throw new NotImplementedException(); } } /*How to use it: BsonSerializer.RegisterSerializer(new PatientObservationAlarmConverter()); JsonConvert.DefaultSettings = () => new JsonSerializerSettings { Converters = { new PatientObservationAlarmConverter() } }; */