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; /// /// Provides conversion logic for values, supporting JSON serialization through and BSON serialization through . /// /// /// The optional constructor parameter specifies the target value type used during conversion. /// public class PatientObservationConverter(Type? valueType) : JsonConverter, IBsonSerializer { /// /// Deserializes a BSON value using the provided deserialization context and arguments. /// /// The deserialization context that provides the BSON reader and configuration. /// The deserialization arguments containing additional information for the operation. /// An object representing the deserialized value. /// Always thrown because the method is not yet implemented. public object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) { throw new NotImplementedException(); } /// /// Serializes the specified value into a BSON format using the provided serialization context and arguments. This implementation is not yet provided and currently throws a . /// /// The BSON serialization context that provides access to the writer and configuration used during serialization. /// The BSON serialization arguments containing additional information that may influence the serialization process. /// The object to be serialized into BSON. /// Thrown because the serialization logic has not been implemented. public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value) { throw new NotImplementedException(); } public Type? ValueType { get; } = valueType; /// /// Serializes a instance to JSON, applying a string enum converter to the Status property and excluding the MessageTime property from the output. If the supplied value is null, nothing is written to the . /// /// The JSON writer that receives the serialized output. /// The patient observation to serialize. When null, the method performs no serialization. /// The JSON serializer used during the conversion process. public override void WriteJson(JsonWriter writer, PatientObservation? value, JsonSerializer serializer) { if (value != null) { var jo = JObject.FromObject(value); // Add [JsonConverter(typeof(StringEnumConverter))] attribute to specified properties AddStringEnumConverterAttribute(value, "Status"); jo.Property("MessageTime")?.Remove(); jo.WriteTo(writer); } } /// /// Adds a JsonConverterAttribute for StringEnumConverter to the specified property if one is not already present. If the property cannot be found on the object's type, the method does nothing. /// /// The object instance whose property should be annotated. /// The name of the property to which the StringEnumConverter attribute should 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); } } } /// /// Deserializes a JSON representation into a instance. /// /// The to read the JSON from. /// The type of the object being deserialized. /// The existing value of the object to populate, or if none. /// Indicates whether contains a value to reuse. /// The used to read nested values. /// A instance produced from the JSON. /// Thrown because the method has not been implemented yet. public override PatientObservation ReadJson(JsonReader reader, Type objectType, PatientObservation? existingValue, bool hasExistingValue, JsonSerializer serializer) { throw new NotImplementedException(); } }