将嵌套 JSON 转换为简单 JSON
Convert nested JSON to simple JSON
我正在尝试通过递归遍历将嵌套的 json 转换为简单的 json。
(输入结构 json 未知)
比如我想要json这样
{
"FirstName": "Rahul",
"LastName": "B",
"EmpType": {
"RID": 2,
"Title": "Full Time"
},
"CTC": "3.5",
"Exp": "1",
"ComplexObj": {
"RID": 3,
"Title": {
"Test": "RID",
"TWO": {
"Test": 12
}
}
}
}
要转换成这样
{
"FirstName": "Rahul",
"LastName": "B",
"EmpType__RID": 2,
"EmpType__Title": "Full Time",
"CTC": "3.5",
"Exp": "1",
"ComplexObj__RID": 3,
"ComplexObj__Title__Test": "RID",
"ComplexObj__Title__TWO__Test": 12
}
嵌套对象中的每个字段将更改为表示其实际路径的键。
这就是我到目前为止所做的。
public static void ConvertNestedJsonToSimpleJson(JObject jobject, ref JObject jobjectRef, string currentNodeName = "", string rootPath = "")
{
string propName = "";
if (currentNodeName.Equals(rootPath))
{
propName = currentNodeName;
}
else
{
propName = (rootPath == "" && currentNodeName == "") ? rootPath + "" + currentNodeName : rootPath + "__" + currentNodeName;
}
foreach (JProperty jprop in jobject.Properties())
{
if (jprop.Children<JObject>().Count() == 0)
{
jobjectRef.Add(propName == "" ? jprop.Name : propName + "__" + jprop.Name, jprop.Value);
}
else
{
currentNodeName = jprop.Name;
rootPath = rootPath == "" ? jprop.Name : rootPath;
ConvertNestedJsonToSimpleJson(JObject.Parse(jprop.Value.ToString()), ref jobjectRef, currentNodeName, rootPath);
}
}
}
得到错误的结果
{
"FirstName": "Rahul",
"LastName": "B",
"EmpType__RID": 2,
"EmpType__Title": "Full Time",
"CTC": "3.5",
"Exp": "1",
"EmpType__ComplexObj__RID": 3,
"EmpType__Title__Test": "RID",
"EmpType__two__Test": 12
}
将感谢任何有关更正我的代码的帮助,或任何其他存档方法。
你能用 linq 做这样的事情吗
var jsonObj = jobject.select(x => new CustomJson {
FirstName = x.FirstName,
LastName = x.LastName,
EmpTypeId = x.EmpType.Id,
Title = x.EmpType.Title
etc etc
});
您的问题在 rootPath = rootPath == "" ? jprop.Name : rootPath;
行。当您第一次遇到 EmpType
时,您正在更改 rootPath,这意味着当您处理 ComplexObj
时,您的 rootPath 是错误的。我相信您的意图只是更改传递给递归函数的内容。
虽然没有必要将根和当前节点作为两个单独的项目进行跟踪。更好的做法是在看起来更像这样的代码中跟踪给定节点的当前前缀:
public static void ConvertNestedJsonToSimpleJson(JObject input, JObject output, string prefix = "")
{
foreach (JProperty jprop in input.Properties())
{
var name = prefix==""?jprop.Name:String.Format("{0}__{1}", prefix,jprop.Name);
if (jprop.Children<JObject>().Count() == 0)
{
output.Add(name, jprop.Value);
}
else
{
ConvertNestedJsonToSimpleJson((JObject)jprop.Value, output, name);
}
}
}
这现在给了我输出:
{
"FirstName": "Rahul",
"LastName": "B",
"EmpType__RID": 2,
"EmpType__Title": "Full Time",
"CTC": "3.5",
"Exp": "1",
"ComplexObj__RID": 3,
"ComplexObj__Title__Test": "RID",
"ComplexObj__Title__TWO__Test": 12
}
看起来正确。
- 您不需要将 属性 的值转换为字符串然后每次都重新解析它 - 只需将其转换为
JObject
- 您不需要复杂的条件逻辑来生成 属性 的名称 - 只需使用:
prefix + jprop.Name + "__"
代码:
public static void FlattenJson(JObject node, JObject result, string prefix = "")
{
foreach (var jprop in node.Properties())
{
if (jprop.Children<JObject>().Count() == 0)
{
result.Add(prefix + jprop.Name, jprop.Value);
}
else
{
FlattenJson((JObject)jprop.Value, $"{prefix}{jprop.Name}__", result);
}
}
}
你可以这样称呼它:
var node = JObject.Parse(/* the input string */);
var result = new JObject();
FlattenJson(node, result);
我正在尝试通过递归遍历将嵌套的 json 转换为简单的 json。 (输入结构 json 未知)
比如我想要json这样
{
"FirstName": "Rahul",
"LastName": "B",
"EmpType": {
"RID": 2,
"Title": "Full Time"
},
"CTC": "3.5",
"Exp": "1",
"ComplexObj": {
"RID": 3,
"Title": {
"Test": "RID",
"TWO": {
"Test": 12
}
}
}
}
要转换成这样
{
"FirstName": "Rahul",
"LastName": "B",
"EmpType__RID": 2,
"EmpType__Title": "Full Time",
"CTC": "3.5",
"Exp": "1",
"ComplexObj__RID": 3,
"ComplexObj__Title__Test": "RID",
"ComplexObj__Title__TWO__Test": 12
}
嵌套对象中的每个字段将更改为表示其实际路径的键。
这就是我到目前为止所做的。
public static void ConvertNestedJsonToSimpleJson(JObject jobject, ref JObject jobjectRef, string currentNodeName = "", string rootPath = "")
{
string propName = "";
if (currentNodeName.Equals(rootPath))
{
propName = currentNodeName;
}
else
{
propName = (rootPath == "" && currentNodeName == "") ? rootPath + "" + currentNodeName : rootPath + "__" + currentNodeName;
}
foreach (JProperty jprop in jobject.Properties())
{
if (jprop.Children<JObject>().Count() == 0)
{
jobjectRef.Add(propName == "" ? jprop.Name : propName + "__" + jprop.Name, jprop.Value);
}
else
{
currentNodeName = jprop.Name;
rootPath = rootPath == "" ? jprop.Name : rootPath;
ConvertNestedJsonToSimpleJson(JObject.Parse(jprop.Value.ToString()), ref jobjectRef, currentNodeName, rootPath);
}
}
}
得到错误的结果
{
"FirstName": "Rahul",
"LastName": "B",
"EmpType__RID": 2,
"EmpType__Title": "Full Time",
"CTC": "3.5",
"Exp": "1",
"EmpType__ComplexObj__RID": 3,
"EmpType__Title__Test": "RID",
"EmpType__two__Test": 12
}
将感谢任何有关更正我的代码的帮助,或任何其他存档方法。
你能用 linq 做这样的事情吗
var jsonObj = jobject.select(x => new CustomJson {
FirstName = x.FirstName,
LastName = x.LastName,
EmpTypeId = x.EmpType.Id,
Title = x.EmpType.Title
etc etc
});
您的问题在 rootPath = rootPath == "" ? jprop.Name : rootPath;
行。当您第一次遇到 EmpType
时,您正在更改 rootPath,这意味着当您处理 ComplexObj
时,您的 rootPath 是错误的。我相信您的意图只是更改传递给递归函数的内容。
虽然没有必要将根和当前节点作为两个单独的项目进行跟踪。更好的做法是在看起来更像这样的代码中跟踪给定节点的当前前缀:
public static void ConvertNestedJsonToSimpleJson(JObject input, JObject output, string prefix = "")
{
foreach (JProperty jprop in input.Properties())
{
var name = prefix==""?jprop.Name:String.Format("{0}__{1}", prefix,jprop.Name);
if (jprop.Children<JObject>().Count() == 0)
{
output.Add(name, jprop.Value);
}
else
{
ConvertNestedJsonToSimpleJson((JObject)jprop.Value, output, name);
}
}
}
这现在给了我输出:
{
"FirstName": "Rahul",
"LastName": "B",
"EmpType__RID": 2,
"EmpType__Title": "Full Time",
"CTC": "3.5",
"Exp": "1",
"ComplexObj__RID": 3,
"ComplexObj__Title__Test": "RID",
"ComplexObj__Title__TWO__Test": 12
}
看起来正确。
- 您不需要将 属性 的值转换为字符串然后每次都重新解析它 - 只需将其转换为
JObject
- 您不需要复杂的条件逻辑来生成 属性 的名称 - 只需使用:
prefix + jprop.Name + "__"
代码:
public static void FlattenJson(JObject node, JObject result, string prefix = "")
{
foreach (var jprop in node.Properties())
{
if (jprop.Children<JObject>().Count() == 0)
{
result.Add(prefix + jprop.Name, jprop.Value);
}
else
{
FlattenJson((JObject)jprop.Value, $"{prefix}{jprop.Name}__", result);
}
}
}
你可以这样称呼它:
var node = JObject.Parse(/* the input string */);
var result = new JObject();
FlattenJson(node, result);