在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);