c#开发过程中,由于json格式繁多,又不想每个格式都去新建类对象去解析,所以就想着能不能动态读取json串;最后折腾出来了,在此记录一下。

首先继承并实现动态类

public class DynamicModel : DynamicObject
    {
        public string PropertyName { get; set; }

        // The inner dictionary.
        protected Dictionary<string, object> DynamicProperty { get; }
             = new Dictionary<string, object>();

        // This property returns the number of elements
        // in the inner dictionary.
        public int Count
        {
            get
            {
                return DynamicProperty.Count;
            }
        }

        // If you try to get a value of a property 
        // not defined in the class, this method is called.
        public override bool TryGetMember(
            GetMemberBinder binder, out object result)
        {
            // Converting the property name to lowercase
            // so that property names become case-insensitive.
            string key = binder.Name;
            if (!DynamicProperty.ContainsKey(key))
            {
                DynamicProperty.Add(key, null);
            }

            // If the property name is found in a dictionary,
            // set the result parameter to the property value and return true.
            // Otherwise, return false.
            result = DynamicProperty[key];
            return true;
        }

        // If you try to set a value of a property that is
        // not defined in the class, this method is called.
        public override bool TrySetMember(
            SetMemberBinder binder, object value)
        {
            // Converting the property name to lowercase
            // so that property names become case-insensitive.
            if (binder.Name == "Property")
            {
                DynamicProperty[PropertyName] = value;
            }
            else
            {
                DynamicProperty[binder.Name] = value;
            }


            // You can always add a value to a dictionary,
            // so this method always returns true.
            return true;
        }

    }

然后是编写动态解析json代码

public static dynamic GetJsonEntity(JObject obj)
        {
            try
            {

                if (!obj.HasValues) { return new DynamicModel(); }
                else
                {

                    JToken head = obj;
                    return GetJObj(obj);
                }
            }
            catch
            {
                return new DynamicModel();
            }
        }

        private static dynamic GetJObj(JToken obj)
        {
            dynamic node = new DynamicModel();
            foreach (JProperty item in obj)
            {
                //节点是数组
                if (item.Value is JArray)
                {
                    node.PropertyName = item.Name;
                    if (!item.Value.HasValues)
                    {
                        node.Property = null;
                        continue;
                    }
                    else if (item.Value[0].Type == JTokenType.Object)
                    {
                        node.Property = GetJArrayObj(item.Value);
                    }
                    else
                    {
                        node.Property = GetJArrayVale(item.Value);
                    }
                }
                //节点值是对象
                else if (item.Value is JObject)
                {
                    node.PropertyName = item.Name;
                    node.Property = GetJObj(item);
                }
                //节点是属性
                else
                {
                    node.PropertyName = item.Name;
                    node.Property = item.Value?.ToString() ?? "";
                }
            }
            return node;

        }

        /// <summary>
        /// 解析Json数组
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        private static List<string> GetJArrayVale(JToken obj)
        {
            List<string> root_array = new List<string>();
            foreach (JValue root_item in obj)
            {

                if (root_item.Type == JTokenType.Integer ||
                   root_item.Type == JTokenType.Float ||
                   root_item.Type == JTokenType.String ||
                   root_item.Type == JTokenType.Boolean ||
                   root_item.Type == JTokenType.Guid)
                {
                    root_array.Add(root_item.Value?.ToString() ?? "");
                }
                else
                {
                    root_array.Add(root_item.Value?.ToString() ?? "");
                }
            }
            return root_array;
        }

        /// <summary>
        /// 解析Json数组对象
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        private static List<dynamic> GetJArrayObj(JToken obj)
        {
            List<dynamic> root_array = new List<dynamic>();
            foreach (JToken root_item in obj)
            {
                dynamic chile_array = new DynamicModel();
                foreach (JProperty child_item in root_item)
                {
                    if (child_item.Value.Type == JTokenType.Array)
                    {
                        chile_array.PropertyName = child_item.Name;
                        if (!child_item.HasValues)
                        {
                            chile_array.Property = null;
                            continue;
                        }
                        else if (child_item.Value.Count() > 0 && child_item.Value[0].Type == JTokenType.Object)
                        {
                            chile_array.Property = GetJArrayObj(child_item.Value);
                        }
                        else
                        {
                            chile_array.Property = GetJArrayVale(child_item.Value);
                        }
                    }
                    else if (child_item.Value.Type == JTokenType.Object)
                    {
                        chile_array.PropertyName = child_item.Name;
                        chile_array.Property = GetJObj(child_item); ;
                    }
                    else
                    {
                        chile_array.PropertyName = child_item.Name;
                        chile_array.Property = child_item.Value?.ToString() ?? "";
                    }
                }
                root_array.Add(chile_array);
            }
            return root_array;
        }

最后是如何调用,其实很简单只需要把json字符串转换成JObject对象传入即可,由于解析出来的类型是动态类型,后面调用字段属性时无智能提示,望知悉。

var obj = JObject.Parse("{\"name\":\"SO JSON在线\",\"url\":\"https://www.sojson.com\",\"address\":{\"city\":\"北京\",\"country\":\"中国\"}}");
         var entity = JsonManager.GetJsonEntity(obj);
最后修改:2022 年 09 月 29 日
如果觉得我的文章对你有用,请随意赞赏