| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591 | using Newtonsoft.Json;using Newtonsoft.Json.Linq;using PTMedicalInsurance.Common;using PTMedicalInsurance.Variables;using System;using System.Collections.Generic;using System.IO;using System.Reflection;namespace PTMedicalInsurance.Helper{    /// <summary>    /// 将json转换为实体对象    /// </summary>    public class JsonMapper    {        const string ArrayPattern = "[]";        private string jsonConfig;        private string configFile;        private JsonMappingSetting setting;        public JsonMapper(string name)        {            configFile = Global.curEvt.path + "/config/" + name + ".json";            reload();        }        public void reload()        {            try            {                // 加载字段映射配置                if (File.Exists(configFile))                {                    jsonConfig = File.ReadAllText(configFile);                    setting = JsonHelper.toObject<JsonMappingSetting>(JObject.Parse(jsonConfig));                }                else                {                    setting = new JsonMappingSetting();                }            }            catch (Exception ex)            {                throw new Exception("配置文件异常:"+ex.Message);            }        }        /// <summary>        /// 获取入参映射        /// </summary>        /// <returns></returns>        public List<FieldMapping> GetInputMapping()        {            return setting.Input??new List<FieldMapping>();        }        /// <summary>        /// 设置入参        /// </summary>        /// <param name="value"></param>        public void SetInputMapping(List<FieldMapping> value)        {            setting.Input = value;        }        /// <summary>        /// 获取出参映射        /// </summary>        /// <returns></returns>        public List<FieldMapping> GetOutputMapping()        {            return setting.Output ?? new List<FieldMapping>();        }        /// <summary>        /// 设置出参        /// </summary>        /// <param name="value"></param>        public void SetOutputMapping(List<FieldMapping> value)        {            setting.Output = value;        }        /// <summary>        /// 获取转换类        /// </summary>        /// <returns></returns>        private ConvertMapping GetConverter()        {            return setting.Convert??new ConvertMapping();        }        /// <summary>        /// 根据实体类获取Json        /// </summary>        /// <param name="typeName"></param>        /// <returns></returns>        private string GetConvertJson(string typeName)        {            if (!string.IsNullOrEmpty(typeName))            {                if (typeName.IndexOf(".")<1)                {                    typeName = "PTMedicalInsurance.Entity.Local." + typeName;                }                Type type = Type.GetType(typeName);                if (type != null)                {                    Object obj = Activator.CreateInstance(type);                    return JsonHelper.toJsonString(obj, false);                }            }            return string.Empty;        }        /// <summary>        /// 将参数方向对调        /// </summary>        public void ChangeDirection(List<FieldMapping> mappings)        {            mappings.ForEach((map) =>            {                if (!string.IsNullOrEmpty(map.Source) && !string.IsNullOrEmpty(map.Target))                {                    string orgin = map.Target;                    map.Target = map.Source;                    map.Source = orgin;                }            });        }        /// <summary>        /// 入参实例JSON        /// </summary>        /// <returns></returns>        public string GetInputJson()        {            return GetConvertJson(GetConverter()?.Input);        }        /// <summary>        /// 出参实例JSON        /// </summary>        /// <returns></returns>        public string GetOutputJson()        {            return GetConvertJson(GetConverter()?.Output);        }        /// <summary>        /// Json字段映射        /// </summary>        /// <param name="jObject"></param>        /// <returns></returns>        private JObject MapJson(string key,JObject jSource)        {            JObject jObject = new JObject();            if(string.IsNullOrEmpty(jsonConfig) || string.IsNullOrEmpty(key))            {                return jSource;            }            List<FieldMapping> fieldMappings = "input".Equals(key) ? GetInputMapping() : GetOutputMapping() ;            if (fieldMappings != null)            {                // 对于每一个字段映射信息                foreach (var fieldMapping in fieldMappings)                {                    if (!string.IsNullOrEmpty(fieldMapping.Target))                    {                        // 单一映射或一对多统一处理                        string[] targets = fieldMapping.Target.Split(",".ToCharArray());                        List<FieldMapping> fields = new List<FieldMapping>();                        foreach (var t in targets)                        {                            fields.Add(new FieldMapping()                            {                                Source = fieldMapping.Source,                                Expression = fieldMapping.Expression,                                Target = t,                                Value = fieldMapping.Value,                                Child = fieldMapping.Child                            }) ;                        }                        fields.ForEach((f) =>                        {                            MapItem(f,jSource,jObject);                        });                    }                    else                    {                        MapItem(fieldMapping, jSource, jObject);                    }                }            }            return jObject;        }        private void MapItem(FieldMapping fieldMapping, JObject jSource, JObject jObject)        {            // 使用JToken.SelectToken来获取源路径对应的值            dynamic value = new JValue("");            string nameKey = fieldMapping.Source;            string expression = fieldMapping.Expression;            if (!string.IsNullOrEmpty(nameKey) && string.IsNullOrEmpty(fieldMapping.Value))            {                nameKey = nameKey.Split(",".ToCharArray())[0];  //多对一忽略后面的                if (fieldMapping.Child != null)                {                    //数组映射                    nameKey = nameKey.Replace(ArrayPattern, "");                }                else                {                    if (nameKey.Contains(ArrayPattern))                    {                        //数组映射对象时,取第一个                        nameKey = nameKey.Replace(ArrayPattern, "[0]");                    }                }                value = jSource.SelectToken(nameKey);            }            else if (fieldMapping.Value != null)            {                // 支持固定值                value = new JValue(fieldMapping.Value);            }            // 表达式(全局变量)            if ((expression ?? "").Equals("GlobaVariables"))            {                value = GetExpressionValue(expression, fieldMapping.Source);                expression = null;            }            // 表达式(扩展字段)            if ((expression ?? "").Equals("SaveToExpand"))            {                SetExpression(expression, fieldMapping.Source, value);                return;            }            string converter = "ShortDate,NoSplitDate,ConvertToString";            if (expression!=null && converter.IndexOf(expression)!=-1)            {                value = GetExpressionValue(expression, value);                expression = null;            }            // 普通转换            if (value != null)            {                if (fieldMapping.Child != null)                {                    Type type = value.GetType();                    var items = new JArray();                    //如果为JValue,则为一对多(忽略此时的name)                    if (type == typeof(JValue))                    {                        JObject sub = new JObject();                         // 此时只返回一条数据的集合                        fieldMapping.Child.ForEach((c) =>                        {                            MapItem(c, jSource, sub);                        });                        items.Add(sub);                    }                    else if (type == typeof(JArray))                    {                        //数组映射,此时的value为array                        foreach (var item in (JArray)value)                        {                            var child = MapChildItem((JObject)item, fieldMapping.Child);                            items.Add(child);                        }                    }                    CreateJObjectFromString(jObject, fieldMapping.Target.Replace(ArrayPattern, ""), items, 0);                }                else                {                    ParseAndMap(value, jObject, nameKey, fieldMapping.Target, expression);                }            }        }        /// <summary>        /// 映射子对象        /// </summary>        /// <param name="itemObject"></param>        /// <param name="childs"></param>        /// <returns></returns>        private JObject MapChildItem(JObject itemObject, List<FieldMapping> childs)        {            JObject newItem = new JObject();            foreach (FieldMapping subMapping in childs)            {                if (subMapping.Value != null)                {                    newItem[subMapping.Target] = subMapping.Value;                }                else                {                    newItem[subMapping.Target] = itemObject[subMapping.Source];                }            }            return newItem;        }        /// <summary>        ///  映射实体        /// </summary>        /// <typeparam name="TSource">源对象</typeparam>        /// <typeparam name="TTarget">目标对象</typeparam>        /// <param name="name">名称</param>        /// <param name="sourceItem">源数据</param>        /// <returns></returns>        public TTarget Map<TSource, TTarget>(string key, TSource sourceItem)        {            var json = JsonConvert.SerializeObject(sourceItem);            var jObject = JObject.Parse(json);            // 映射            JObject jRet = MapJson(key,jObject);            // 然后将修改后的JObject再转化到目标类型的对象            var targetItem = jRet.ToObject<TTarget>();            return targetItem;        }        /// <summary>        /// 解析对象后转换为JObject        /// </summary>        /// <typeparam name="TSource"></typeparam>        /// <typeparam name="TTarget"></typeparam>        /// <param name="sourceItem"></param>        /// <returns></returns>        //[Obsolete("建议使用Map方法")]        private JObject MapObject<TSource, TTarget>(string key,TSource sourceItem)        {            TTarget target = Map<TSource, TTarget>(key,sourceItem);            var json = JsonConvert.SerializeObject(target);            return JObject.Parse(json);        }        /// <summary>        /// 入参映射        /// </summary>        /// <typeparam name="TSource"></typeparam>        /// <typeparam name="TTarget"></typeparam>        /// <param name="sourceItem"></param>        /// <returns></returns>        public JObject MapRequest<TSource, TTarget>(TSource sourceItem)        {            TTarget target = Map<TSource, TTarget>("input",sourceItem);            var json = JsonConvert.SerializeObject(target);            return JObject.Parse(json);        }        /// <summary>        /// 出参映射        /// </summary>        /// <typeparam name="TSource"></typeparam>        /// <typeparam name="TTarget"></typeparam>        /// <param name="sourceItem"></param>        /// <returns></returns>        public JObject MapResponse<TSource, TTarget>(TSource sourceItem)        {            TTarget target = Map<TSource, TTarget>("output", sourceItem);            var json = JsonConvert.SerializeObject(target);            return JObject.Parse(json);        }        /// <summary>        /// 解析并映射字段        /// </summary>        /// <param name="sourceToken"></param>        /// <param name="targetObject"></param>        /// <param name="sourcePath"></param>        /// <param name="targetPath"></param>        private void ParseAndMap(JToken sourceToken, JObject targetObject, string sourcePath, string targetPath, string expression = "")        {            // 支持映射多个字段            var targetFields = targetPath.Split(',');            foreach (var targetField in targetFields) {                //if (!sourceToken.HasValues && string.IsNullOrEmpty(sourceToken.Value<string>())) continue;                ParseAndMapField(sourceToken, targetObject, sourcePath, targetField, expression);            }        }        /// <summary>        /// 解析并映射单个字段        /// </summary>        /// <param name="sourceToken"></param>        /// <param name="targetObject"></param>        /// <param name="sourcePath"></param>        /// <param name="targetPath"></param>        private void ParseAndMapField(JToken value, JObject targetObject, string sourcePath, string targetPath, string expression = "")        {            if (string.IsNullOrEmpty(targetPath)) return;            if (sourcePath !=null && sourcePath.StartsWith(".")) { sourcePath = sourcePath.Substring(1); }            if (targetPath.StartsWith(".")) { targetPath = targetPath.Substring(1); }            var targetTokens = targetPath.Split('.');            var remainingTargetPath = string.Join(".", targetTokens, 0, targetTokens.Length - 1);            var isArray = remainingTargetPath.Contains(ArrayPattern);            var remainingTargetTokens = remainingTargetPath.Split(ArrayPattern.ToCharArray());            //var value = sourceToken.SelectToken(sourcePath);            // 抵达路径顶点            if (targetTokens.Length == 1)            {                targetObject.Add(targetTokens[0], value);                return;            }            // 处理数组类型的映射            if (isArray)            {                if (value is JValue) {                    // 将固定数据给数组中的第一个对象                    var newItem = (targetObject[targetTokens[0]] ?? new JObject()) as JObject;                    CreateJObjectFromString(newItem, targetPath, (JValue)value,1,expression);                    targetObject[targetTokens[0]] = newItem;                }                //if (value is JArray)                //{                //    string[] childPath = sourcePath.Split(ArrayPattern.ToCharArray());                //    string[] destPath = targetPath.Split(ArrayPattern.ToCharArray());                //    string arrayKey = targetTokens[0].Split(ArrayPattern.ToCharArray())[0];                //    var newItem = (targetObject[arrayKey] ?? new JArray()) as JArray;                //    //CreateJObjectFromString(newItem, targetPath, null,0);                //    foreach (var item in ((JArray)value).Children<JObject>())                //    {                //        var childItem = new JObject();                //        ParseAndMapField(item.SelectToken(childPath[2].Substring(1)), childItem, childPath[2], destPath[2]); // 递归处理嵌套路径                //        newItem.Add(childItem);                //    }                //    targetObject[arrayKey] = newItem;                //}            }            else if (targetTokens.Length > 1) {                // 对象层级                string nameKey = targetTokens[0];                int index = 1; //不包含根节点                if (nameKey.Contains("[]"))                {                    nameKey = nameKey.Substring(0, nameKey.Length - 2);                    index = 0;                }                var newItem = (targetObject[nameKey] ?? new JObject()) as JObject;                CreateJObjectFromString(newItem,targetPath,(JValue)value, index, expression);                targetObject[nameKey] = newItem;            }            else // 普通嵌套映射            {                var newItem = new JObject();                ParseAndMapField(value, newItem, sourcePath, remainingTargetPath); // 递归处理嵌套路径                targetObject.Add(targetTokens[0], newItem);            }            targetObject.Remove(sourcePath);        }        /// <summary>        /// 根据层级创建对象        /// </summary>        /// <param name="current"></param>        /// <param name="input"></param>        /// <param name="value"></param>        /// <returns></returns>        private JObject CreateJObjectFromString(JObject current, string input,JToken value,int index = 1,string expression = "")        {            var keys = input.Split('.');            JObject root = current;                        for (int i = index; i < keys.Length - 1; i++)            {                if (keys[i].EndsWith("[]"))                {                    string actualKey = keys[i].Substring(0, keys[i].Length - 2);                    if (current[actualKey] == null)                    {                        current[actualKey] = new JArray { new JObject() };                    }                    // 数组的某一条                    current = (JObject)((JArray)current[actualKey]).Last; ;                }                else                {                    if (current[keys[i]] == null)                    {                        current[keys[i]] = new JObject();                    }                    current = (JObject)current[keys[i]];                }            }            if (!string.IsNullOrEmpty(expression)) {                value = GetExpressionValue(expression, value);            }            current[keys[keys.Length - 1]] = value;            return root;        }        private void SetExpression(string method, string key,object value)        {            try            {                Type type = typeof(ExpressionEvaluator);                MethodInfo mi = type.GetMethod(method);                if (mi != null)                {                    mi.Invoke(null, new object[] {key,value });                }            }            catch (Exception e)            { }        }        private string GetExpressionValue(string method,object value)        {            object objRtn = null;            try            {                Type type = typeof(ExpressionEvaluator);                MethodInfo mi = type.GetMethod(method);                if (mi != null)                {                    objRtn = mi.Invoke(null, new object[] { value });                }            }            catch (Exception e)            { }            return objRtn?.ToString();        }        /// <summary>        /// 保存配置        /// </summary>        public void Save()        {            jsonConfig = JsonHelper.toJsonString(this.setting);            if(!string.IsNullOrEmpty(jsonConfig) && !string.IsNullOrEmpty(configFile))            {                File.WriteAllText(configFile,jsonConfig);            }        }    }    public class JsonMappingSetting    {         public List<FieldMapping> Input { set; get; }        public List<FieldMapping> Output { set; get; }        public ConvertMapping Convert { set; get; }    }    public class FieldMapping    {        public string Source { get; set; }        public string Target { get; set; }        public string Value { get; set; }        public string Expression { set; get; }        public string Name { get; set; }        public List<FieldMapping> Child { get; set; }        public FieldMapping()        { }    }    public class ConvertMapping    {         public string Input { set; get; }        public string Output { set; get; }    }}
 |