using adas_core.Domain.Models.MongoModels; using MongoDB.Bson; using MongoDB.Bson.IO; using MongoDB.Bson.Serialization; using MongoDB.Bson.Serialization.Serializers; using Newtonsoft.Json.Linq; namespace adas_core.Domain.Models.BsonConverters; public class DictionaryBsonConverter : SerializerBase> { public override Dictionary Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) { var reader = context.Reader; var stepsDictionary = new Dictionary(); if (reader.CurrentBsonType == BsonType.Document) { reader.ReadStartDocument(); while (reader.ReadBsonType() != BsonType.EndOfDocument) { var key = reader.ReadName(); switch (key.ToUpper()) { case "STEPS": var stepList = BsonSerializer.Deserialize>(reader); stepsDictionary[key] = stepList; break; case "BEACONS": var beaconList = BsonSerializer.Deserialize>(reader); stepsDictionary[key] = beaconList; break; case "CAMERAS": var cameraList = BsonSerializer.Deserialize>(reader); stepsDictionary[key] = cameraList; break; case "RELAY": var relayList = BsonSerializer.Deserialize(reader); stepsDictionary[key] = relayList; break; default: switch (reader.CurrentBsonType) { case BsonType.Int32: case BsonType.Int64: stepsDictionary[key] = BsonSerializer.Deserialize(reader); break; case BsonType.Double: stepsDictionary[key] = BsonSerializer.Deserialize(reader); break; case BsonType.String: stepsDictionary[key] = BsonSerializer.Deserialize(reader); break; case BsonType.Boolean: stepsDictionary[key] = BsonSerializer.Deserialize(reader); break; case BsonType.Array: reader.ReadStartArray(); var arrayItems = new List(); while (reader.ReadBsonType() != BsonType.EndOfDocument) switch (reader.CurrentBsonType) { case BsonType.String: arrayItems.Add(BsonSerializer.Deserialize(reader)); break; case BsonType.Int32: arrayItems.Add(BsonSerializer.Deserialize(reader)); break; case BsonType.Int64: arrayItems.Add(BsonSerializer.Deserialize(reader)); break; case BsonType.Boolean: arrayItems.Add(BsonSerializer.Deserialize(reader)); break; case BsonType.Double: arrayItems.Add(BsonSerializer.Deserialize(reader)); break; case BsonType.ObjectId: arrayItems.Add(BsonSerializer.Deserialize(reader)); break; case BsonType.DateTime: arrayItems.Add(BsonSerializer.Deserialize(reader)); break; default: reader.SkipValue(); break; } reader.ReadEndArray(); stepsDictionary[key] = arrayItems; break; default: var bsonDoc = BsonSerializer.Deserialize(reader); stepsDictionary[key] = bsonDoc.ToDictionary(); break; } break; } } reader.ReadEndDocument(); } return stepsDictionary; } public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Dictionary value) { var writer = context.Writer; writer.WriteStartDocument(); foreach (var item in value) { if (TrySerializeKeyValuePair(item, writer)) continue; // Si llegamos a este punto, encontramos un tipo no soportado. writer.WriteName(item.Key); writer.WriteNull(); // Escribe un valor null si el tipo no es soportado. } writer.WriteEndDocument(); } private static bool TrySerializeKeyValuePair(KeyValuePair item, IBsonWriter writer) { writer.WriteName(item.Key); switch (item.Key) { case "steps": if (item.Value is JArray jSteps) { var steps = jSteps.ToObject>(); BsonSerializer.Serialize(writer, typeof(List), steps); return true; } break; case "beacons": if (item.Value is JArray jBeaconConfigs) { var beaconConfigs = jBeaconConfigs.ToObject>(); BsonSerializer.Serialize(writer, typeof(List), beaconConfigs); return true; } break; case "cameras": if (item.Value is JArray jCamerasConfigs) { var cameraConfigs = jCamerasConfigs.ToObject>(); BsonSerializer.Serialize(writer, typeof(List), cameraConfigs); return true; } break; case "relay": if (item.Value is JObject jRelayConfigs) { var relayConfigs = jRelayConfigs.ToObject(); BsonSerializer.Serialize(writer, relayConfigs); return true; } break; case "uiFontProperties": { if (item.Value is JObject jUiFontData) { var uiFontData = jUiFontData.ToObject(); BsonSerializer.Serialize(writer, uiFontData); return true; } } break; default: if (item.Value is Dictionary nestedDictionary) { var bsonDoc = new BsonDocument(nestedDictionary); BsonSerializer.Serialize(writer, bsonDoc); return true; } if (item.Value is JArray jArray) { var listObjects = jArray.ToObject>(); BsonSerializer.Serialize(writer, listObjects); return true; } // Para otros tipos primitivos, utilizamos BsonValue.Create try { var bsonValue = BsonValue.Create(item.Value); switch (bsonValue.BsonType) { case BsonType.String: writer.WriteString(bsonValue.AsString); break; case BsonType.Int32: writer.WriteInt32(bsonValue.AsInt32); break; case BsonType.Int64: writer.WriteInt64(bsonValue.AsInt64); break; case BsonType.Double: writer.WriteDouble(bsonValue.AsDouble); break; case BsonType.Boolean: writer.WriteBoolean(bsonValue.AsBoolean); break; case BsonType.Array: writer.WriteStartArray(); foreach (var arrayValue in bsonValue.AsBsonArray) switch (arrayValue.BsonType) { case BsonType.String: writer.WriteString(arrayValue.AsString); break; case BsonType.Int32: writer.WriteInt32(arrayValue.AsInt32); break; case BsonType.Int64: writer.WriteInt64(arrayValue.AsInt64); break; case BsonType.Double: writer.WriteDouble(arrayValue.AsDouble); break; case BsonType.Boolean: writer.WriteBoolean(arrayValue.AsBoolean); break; default: throw new BsonSerializationException( $"No se puede serializar el tipo Bson en el array: {arrayValue.BsonType}"); } writer.WriteEndArray(); break; default: throw new NotSupportedException($"BsonType {bsonValue.BsonType} no es compatible."); } return true; } catch (ArgumentException) { return false; } } return false; } }