// // ReSharper disable All // Disable StyleCop analysis for this file // // Copyright (c) Manus. All rights reserved. // using medical.transfomer.dto; using System; using System.Collections.Generic; using System.Linq; using System.Text.Json; using System.Text.Json.Nodes; namespace medical.insu.transfomer { /// /// JSON配置转换服务类 /// public class TransformerService { private readonly TransformationConfig _config; private readonly IValueConverter _valueConverter; // 用于字典转换等 /// /// 构造函数 /// /// 转换配置 /// 值转换器实例 (可选) public TransformerService(TransformationConfig configuration, IValueConverter valueConverter = null) { _config = configuration ?? throw new ArgumentNullException(nameof(configuration)); _valueConverter = valueConverter ?? new DefaultValueConverter(); // 提供一个默认实现 } /// /// 从JSON字符串加载配置 /// /// 包含配置的JSON字符串 /// TransformationConfig 实例 public static TransformationConfig LoadConfigFromJson(string jsonConfig) { if (string.IsNullOrWhiteSpace(jsonConfig)) { throw new ArgumentException("JSON configuration string cannot be null or empty.", nameof(jsonConfig)); } try { return JsonSerializer.Deserialize(jsonConfig, new JsonSerializerOptions { PropertyNameCaseInsensitive = true // 允许属性名不区分大小写 }); } catch (JsonException ex) { // 在实际应用中,这里应该记录更详细的错误日志 throw new InvalidOperationException("Failed to deserialize JSON configuration.", ex); } } /// /// 将源数据对象根据指定方法转换为目标JSON字符串 (系统对象 -> 接口JSON) /// /// 方法名称 (来自 method_config) /// 源数据对象 (通常是一个C#对象或字典) /// 转换后的JSON字符串 public string Transform(string methodName, object sourceObject) { // 1. 查找方法配置 var method = _config.MethodConfigs.FirstOrDefault(m => m.METHOD_NAME == methodName); if (method == null) { throw new ArgumentException($"Method '{methodName}' not found in configuration.", nameof(methodName)); } // 2. 筛选出适用于当前方法和出参的组装规则 (parametr_type = 2 代表出参) var assemblyRules = _config.ObjectAssemblies .Where(a => a.METHOD_REF == method.METHOD_ID && a.PARAMETR_TYPE == 2 && a.ASSEMBLY_TYPE == "interface") // 假设是系统到接口的转换 .OrderBy(a => a.OBJECT_PATH) // 排序以确保父节点先创建 .ToList(); if (!assemblyRules.Any()) { // 如果没有找到针对出参的interface类型组装规则,可能需要抛出错误或返回空JSON // 根据实际需求,这里也可以查找 'sys' 类型的规则,取决于转换方向的定义 Console.WriteLine($"Warning: No 'interface' assembly rules found for method '{methodName}' and parameter type 2 (output)."); return "{}"; // 或者抛出异常 } var rootNode = new JsonObject(); // 创建JSON根节点 // 3. 遍历组装规则,构建JSON foreach (var rule in assemblyRules) { // 3.1 查找对应的映射规则 (通过MappingTable关联到ObjectMapping的ObjectTableName或MappingId) // 假设 MappingTable 直接对应 ObjectMapping 中的 ObjectTableName var mapping = _config.ObjectMappings.FirstOrDefault(om => om.OBJECT_TABLE_NAME == rule.MAPPING_TABLE && om.INTERFACE_FIELD != null); // 如果MappingTable也可能是MappingId, 则需要调整查找逻辑 // var mapping = _config.ObjectMappings.FirstOrDefault(om => // (om.ObjectTableName == rule.MappingTable || om.MappingId == rule.MappingTable) && // om.InterfaceField != null); if (mapping == null) { Console.WriteLine($"Warning: No object mapping found for MappingTable '{rule.MAPPING_TABLE}' in assembly rule '{rule.ID}'. Skipping path '{rule.OBJECT_PATH}'."); continue; } // 3.2 从源对象获取值 // 这里简化处理,假设sourceObject是字典或可以通过反射获取属性 // 实际应用中需要更健壮的取值逻辑 object sourceValue = GetValueFromSourceObject(sourceObject, mapping.SYSTEM_FIELD); if (sourceValue == null && rule.OBJECT_PATH.Contains("patientId")) // 示例:特定字段的空值处理 { // Console.WriteLine($"Debug: Source value for {mapping.SystemField} is null."); } // 3.3 值转换 (字典翻译、类型转换等) object convertedValue = _valueConverter.Convert( sourceValue, mapping.SYSTEM_FIELD_TYPE?.ToString(), // Convert decimal? to string mapping.OBJECT_FIELD_TYPE?.ToString(), // Convert decimal? to string mapping.SYSTEM_DICT_NAME, mapping.OBJECT_DICT_NAME, rule.PARAMETR_TYPE ); // 3.4 根据ObjectPath设置值到JSON节点 SetValueByJsonPath(rootNode, rule.OBJECT_PATH, convertedValue, rule.OBJECT_TYPE); } return rootNode.ToJsonString(new JsonSerializerOptions { WriteIndented = true }); } /// /// 从源对象中获取指定属性的值 (简化实现) /// private object GetValueFromSourceObject(object source, string propertyName) { if (source == null || string.IsNullOrEmpty(propertyName)) return null; if (source is IDictionary dictSource) { return dictSource.TryGetValue(propertyName, out var val) ? val : null; } if (source is JsonElement jsonElementSource && jsonElementSource.ValueKind == JsonValueKind.Object) { return jsonElementSource.TryGetProperty(propertyName, out var prop) ? GetValueFromJsonElement(prop) : null; } // 尝试通过反射获取属性值 var propInfo = source.GetType().GetProperty(propertyName); if (propInfo != null) { return propInfo.GetValue(source); } // 如果是JsonNode,尝试获取 if (source is JsonNode jnSource) { var parts = propertyName.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries); JsonNode currentNode = jnSource; foreach (var part in parts) { if (currentNode is JsonObject jo && jo.ContainsKey(part)) { currentNode = jo[part]; } else { return null; // 路径不存在 } } if (currentNode is JsonValue jv) return jv.GetValue(); return currentNode; //可能是JsonObject或JsonArray } Console.WriteLine($"Warning: Property '{propertyName}' not found in source object of type '{source.GetType().Name}'."); return null; } private object GetValueFromJsonElement(JsonElement element) { switch (element.ValueKind) { case JsonValueKind.String: return element.GetString(); case JsonValueKind.Number: if (element.TryGetInt32(out int i)) return i; if (element.TryGetInt64(out long l)) return l; if (element.TryGetDouble(out double d)) return d; return element.GetDecimal(); // Fallback case JsonValueKind.True: return true; case JsonValueKind.False: return false; case JsonValueKind.Null: return null; case JsonValueKind.Object: return element; // Or parse to dictionary case JsonValueKind.Array: return element; // Or parse to list default: return null; } } /// /// 根据JSONPath在JsonNode中设置值 (简化实现, 支持基本的路径) /// private void SetValueByJsonPath(JsonNode rootNode, string path, object value, int objectType) { if (string.IsNullOrWhiteSpace(path) || rootNode == null) return; // 移除起始的 "$." if (path.StartsWith("$.")) { path = path.Substring(2); } var segments = path.Split('.'); JsonNode currentNode = rootNode; for (int i = 0; i < segments.Length - 1; i++) { var segment = segments[i]; if (currentNode[segment] == null) { // 根据下一个segment是否是数组索引来决定创建JsonObject还是JsonArray // 此处简化:如果下一个路径是数字,则认为是数组索引,但设计文档中object_type更可靠 // 暂时简单处理,都创建JsonObject,实际应根据object_assembly的object_type判断 currentNode[segment] = new JsonObject(); } currentNode = currentNode[segment]; if (currentNode == null) // 防御性编程,如果中间节点创建失败或路径无效 { Console.WriteLine($"Error: Could not navigate or create path segment '{segment}' in JSON path '{path}'."); return; } } var lastSegment = segments.Last(); JsonNode valueNode = value == null ? null : JsonValue.Create(value); // JsonValue.Create可以处理多种基本类型 if (value is JsonElement je) { valueNode = JsonNode.Parse(je.GetRawText()); } else if (value is IDictionary dictValue) { valueNode = new JsonObject(); foreach(var kvp in dictValue) { ((JsonObject)valueNode).Add(kvp.Key, JsonValue.Create(kvp.Value)); } } else if (value is IEnumerable listValue && !(value is string)) // 确保不是字符串 { var jsonArray = new JsonArray(); foreach (var item in listValue) { jsonArray.Add(JsonValue.Create(item)); } valueNode = jsonArray; } if (objectType == 2) // 列表类型 { if (currentNode[lastSegment] == null || !(currentNode[lastSegment] is JsonArray)) { currentNode[lastSegment] = new JsonArray(); } ((JsonArray)currentNode[lastSegment]).Add(valueNode); } else // 对象类型 { ((JsonObject)currentNode)[lastSegment] = valueNode; } } /// /// 将接口JSON字符串根据指定方法转换为目标系统对象 (接口JSON -> 系统对象) /// /// 期望的目标系统对象类型 /// 方法名称 (来自 method_config) /// 源JSON字符串 /// 转换后的目标系统对象 public T Transform(string methodName, string sourceJson) where T : new() { // 1. 查找方法配置 var method = _config.MethodConfigs.FirstOrDefault(m => m.METHOD_NAME == methodName); if (method == null) { throw new ArgumentException($"Method '{methodName}' not found in configuration.", nameof(methodName)); } // 2. 解析源JSON JsonNode sourceNode; try { sourceNode = JsonNode.Parse(sourceJson); } catch (JsonException ex) { throw new ArgumentException("Invalid source JSON string.", nameof(sourceJson), ex); } if (sourceNode == null) throw new ArgumentException("Parsed source JSON is null.", nameof(sourceJson)); // 3. 筛选出适用于当前方法和入参的组装规则 (parametr_type = 1 代表入参) var assemblyRules = _config.ObjectAssemblies .Where(a => a.METHOD_REF == method.METHOD_ID && a.PARAMETR_TYPE == 1 && a.ASSEMBLY_TYPE == "sys") // 假设是接口到系统的转换 .OrderBy(a => a.OBJECT_PATH) .ToList(); if (!assemblyRules.Any()) { Console.WriteLine($"Warning: No 'sys' assembly rules found for method '{methodName}' and parameter type 1 (input)."); return new T(); // 或者抛出异常 } T targetObject = new T(); // 4. 遍历组装规则, 填充目标对象 foreach (var rule in assemblyRules) { var mapping = _config.ObjectMappings.FirstOrDefault(om => om.OBJECT_TABLE_NAME == rule.MAPPING_TABLE && om.SYSTEM_FIELD != null); if (mapping == null) { Console.WriteLine($"Warning: No object mapping found for MappingTable '{rule.MAPPING_TABLE}' in assembly rule '{rule.ID}'. Skipping path '{rule.OBJECT_PATH}'."); continue; } // 4.1 从源JSON获取值 object sourceValue = GetValueByJsonPath(sourceNode, rule.OBJECT_PATH); // 4.2 值转换 object convertedValue = _valueConverter.Convert(sourceValue, mapping.OBJECT_FIELD_TYPE, mapping.SYSTEM_FIELD_TYPE, mapping.OBJECT_DICT_NAME, mapping.SYSTEM_DICT_NAME, rule.PARAMETR_TYPE); // 4.3 设置到目标对象属性 (简化实现, 假设属性名与SystemField一致) // 实际应用中可能需要更复杂的属性设置逻辑,例如处理嵌套对象 var propInfo = typeof(T).GetProperty(mapping.SYSTEM_FIELD); if (propInfo != null && propInfo.CanWrite) { try { // 类型转换,确保赋的值与属性类型匹配 var typedValue = ConvertToPropertyType(convertedValue, propInfo.PropertyType); propInfo.SetValue(targetObject, typedValue); } catch (Exception ex) { Console.WriteLine($"Error setting property '{mapping.SYSTEM_FIELD}': {ex.Message}"); } } else { Console.WriteLine($"Warning: Property '{mapping.SYSTEM_FIELD}' not found or not writable on type '{typeof(T).Name}'."); } } return targetObject; } /// /// 根据JSONPath从JsonNode中获取值 (简化实现) /// private object GetValueByJsonPath(JsonNode rootNode, string path) { if (string.IsNullOrWhiteSpace(path) || rootNode == null) return null; if (path.StartsWith("$.")) path = path.Substring(2); var segments = path.Split('.'); JsonNode currentNode = rootNode; foreach (var segment in segments) { if (currentNode is JsonObject jo && jo.ContainsKey(segment)) { currentNode = jo[segment]; } // TODO: Add support for array indexing if needed, e.g., "items[0].name" else { return null; // 路径不存在 } } if (currentNode is JsonValue jv) return jv.GetValue(); // GetValue 会尝试转换为合适的.NET类型 return currentNode; //可能是JsonObject或JsonArray,调用者需要进一步处理 } /// /// 将值转换为目标属性类型 (简化实现) /// private object ConvertToPropertyType(object value, Type targetType) { if (value == null) return null; if (targetType.IsAssignableFrom(value.GetType())) return value; try { return Convert.ChangeType(value, targetType); } catch { // 对于复杂类型或JsonElement,可能需要特殊处理 if (value is JsonElement je && targetType == typeof(string)) return je.ToString(); // 添加更多转换逻辑... return null; } } } /// /// 值转换器接口 (用于字典翻译、类型转换等) /// public interface IValueConverter { /// /// 执行值转换 /// /// 源值 /// 源类型字符串 (来自配置) /// 目标类型字符串 (来自配置) /// 源字典名称 (来自配置) /// 目标字典名称 (来自配置) /// 参数方向 (1入参,2出参) /// 转换后的值 object Convert(object sourceValue, string sourceType, string targetType, string sourceDictName, string targetDictName, int paramDirection); object Convert(object sourceValue, decimal? oBJECT_FIELD_TYPE, decimal? sYSTEM_FIELD_TYPE, string oBJECT_DICT_NAME, string sYSTEM_DICT_NAME, int pARAMETR_TYPE); } /// /// 默认的值转换器实现 (简单类型转换,无字典转换) /// public class DefaultValueConverter : IValueConverter { public object Convert(object sourceValue, string sourceType, string targetType, string sourceDictName, string targetDictName, int paramDirection) { // 简单示例:如果类型字符串匹配C#类型,尝试转换 if (sourceValue == null) return null; try { Type targetTypeResolved = Type.GetType(targetType) ?? typeof(object); return System.Convert.ChangeType(sourceValue, targetTypeResolved); } catch { return sourceValue; } } public object Convert(object sourceValue, decimal? objectFieldType, decimal? systemFieldType, string objectDictName, string systemDictName, int paramDirection) { // 示例实现:直接返回源值,实际应用中需要根据字段类型和字典名称进行转换 return sourceValue; } } }