前言
技术群里面一个哥们在群里提了一个问题,怎么把Json的树形结构展平成一层
在线Json格式化工具
将这个JSON
展平成这样
代码
使用方法
static void Main(string[] args)
{
//将测试对象转换成测试Json
var json = JsonConvert.SerializeObject(new
{
Id = 1,
Name = "张三",
Childs = new[]
{
new
{
Id = 2,
Name = "李四"
},
new
{
Id = 3,
Name = "王五"
}
},
Dogs = new []
{
new
{
Id = 10,
DogName = "来福"
}
}
});
//使用Newtonsoft.Json解析Json字符串获取Json结构对象
var jObject = (JToken)JsonConvert.DeserializeObject(json);
//调用展平Json函数得到展平后的对象列表
var result = FlattenJsonUtil.Flatten(jObject, null);
//将展平后的对象列表转换成Json字符串
var rJson = FlattenJsonUtil.ToJson(result);
//将展平后的Json字符串输出到控制台上
Console.WriteLine(rJson);
}
展平Json帮助类
public class FlattenJsonUtil
{
public class JsonKey
{
/// <summary>
/// 键名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 父亲节点
/// </summary>
public JsonKey Parent { get; set; }
/// <summary>
/// 创建新Key
/// </summary>
public static JsonKey CreateKey(JsonKey parentKey, string name)
{
return new JsonKey
{
Parent = parentKey,
Name = name
};
}
public override string ToString()
{
var names = new List<string>();
for (var i = this; i != null; i = i.Parent)
{
names.Add(i.Name);
}
names.Reverse();
return string.Join("_", names);
}
}
public class JsonNode
{
/// <summary>
/// 键值
/// </summary>
public JsonKey Key { get; set; }
/// <summary>
/// 字符串、数字、null、日期
/// </summary>
public string Value { get; set; }
/// <summary>
/// 前面的节点
/// </summary>
public JsonNode Previous { get; set; }
/// <summary>
/// 复制并设置前面对象
/// </summary>
public JsonNode CopyAndSetPrevious(JsonNode jsonNode)
{
List<JsonNode> nodes = new List<JsonNode>()
{
this
};
var top = this;
while (top.Previous != null)
{
top = top.Previous;
nodes.Add(top);
}
var last = jsonNode;
//循环克隆一遍
for (var i = nodes.Count - 1; i >= 0; i--)
{
var node = nodes[i];
last = new JsonNode
{
Key = node.Key,
Previous = last,
Value = node.Value
};
}
return last;
}
public override string ToString()
{
var items = new List<string>();
for (var i = this; i != null; i = i.Previous)
{
items.Add($"\"{i.Key}\":{i.Value}");
}
items.Reverse();
return $"{{{string.Join(",", items)}}}";
}
}
public static string ToJson(List<JsonNode> nodes)
{
return $"[{string.Join(",", nodes)}]";
}
/// <summary>
/// 展平Json
/// </summary>
public static List<JsonNode> Flatten(JToken json, JsonKey parentKey)
{
//对象
if (json.Type == JTokenType.Object)
{
List<JsonNode> result = new List<JsonNode>();
foreach (var property in ((JObject)json).Properties())
{
var key = JsonKey.CreateKey(parentKey, property.Name);
var value = Flatten(property.Value, key);
result = MergeJsonNodes(result, value);
}
return result;
}
if (json.Type == JTokenType.Array)
{
List<JsonNode> result = new List<JsonNode>();
foreach (var jToken in (JArray)json)
{
var value = Flatten(jToken, parentKey);
result.AddRange(value);
}
return result;
}
return new List<JsonNode>
{
new JsonNode
{
Key = parentKey,
Value = JsonValueToString(json)
}
};
}
private static string JsonValueToString(JToken json)
{
if (json.Type == JTokenType.String || json.Type == JTokenType.Date)
{
return $"\"{json}\"";
}
return json.ToString();
}
/// <summary>
/// 合并结果集
/// </summary>
private static List<JsonNode> MergeJsonNodes(List<JsonNode> result, List<JsonNode> value)
{
if (result.Count == 0)
{
return value;
}
if (value.Count == 1)
{
var first = value.First();
return result.Select(x => first.CopyAndSetPrevious(x)).ToList();
}
return result.SelectMany(r => value.Select(v => v.CopyAndSetPrevious(r))).ToList();
}
}