C# JSON序列化-如何使用JSON.net/Newtonsoft展平嵌套对象结构
我有以下JSON结构:C# JSON序列化-如何使用JSON.net/Newtonsoft展平嵌套对象结构,c#,json,serialization,json.net,C#,Json,Serialization,Json.net,我有以下JSON结构: { "Name":"", "Children":[ { "ID":"1", "MetaData":[ { "Info":{ "GUID":"cdee360d-7ea9-477d-994f-12f492b9e1ed" },
{
"Name":"",
"Children":[
{
"ID":"1",
"MetaData":[
{
"Info":{
"GUID":"cdee360d-7ea9-477d-994f-12f492b9e1ed"
},
"Data":{
"Text":"8"
},
"Name":"DataId"
}
]
}
]
}
我想展平数组中的元数据、嵌套信息和数据对象。我还想使用Name字段作为文本值的字段名,使其成为“DataId”:“8”
到目前为止,我已经使用了一个合同解析程序:
private class DynamicContractResolver : DefaultContractResolver
{
private readonly List<string> _propertiesToSerialize;
private readonly List<string> _itemTypeNames;
public DynamicContractResolver(List<string> propertiesToSerialize, List<string> itemTypeNames)
{
_propertiesToSerialize = propertiesToSerialize;
_itemTypeNames = itemTypeNames;
}
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
var properties = base.CreateProperties(type, memberSerialization);
properties = properties.Where(p => _propertiesToSerialize.Contains(p.PropertyName)).ToList();
}
return properties;
}
}
私有类DynamicContractResolver:DefaultContractResolver
{
私有只读列表_propertiesToSerialize;
私有只读列表_itemTypeNames;
公共DynamicContractResolver(列表属性序列化,列表项类型名称)
{
_propertiesToSerialize=propertiesToSerialize;
_itemTypeNames=itemTypeNames;
}
受保护的重写IList CreateProperties(类型类型,MemberSerialization MemberSerialization)
{
var properties=base.CreateProperties(类型、成员序列化);
properties=properties.Where(p=>_propertiesToSerialize.Contains(p.PropertyName)).ToList();
}
归还财产;
}
}
如何获得所需的序列化?如果您根本不想修改类型,可以使用加载和预处理JSON,如下所示:
// Load the JSON into an intermediate JObject
var rootObj = JObject.Parse(json);
// Restructure the JObject hierarchy
foreach (var obj in rootObj.SelectTokens("Children[*]").OfType<JObject>())
{
var metadata = obj.SelectToken("MetaData[0]"); // Get the first entry in the "MetaData" array.
if (metadata != null)
{
// Remove the entire "Metadata" property.
metadata.Parent.RemoveFromLowestPossibleParent();
// Set the name and value
var name = metadata.SelectToken("Name");
var id = metadata.SelectToken("Data.Text");
if (name != null && id != null)
obj[(string)name] = (string)id;
// Move all other atomic values.
foreach (var value in metadata.SelectTokens("..*").OfType<JValue>().Where(v => v != id && v != name).ToList())
value.MoveTo(obj);
}
}
Debug.WriteLine(rootObj);
// Now deserialize the preprocessed JObject to the final class
var root = rootObj.ToObject<RootObject>();
//将JSON加载到中间作业对象中
var rootObj=JObject.Parse(json);
//重新构造JObject层次结构
foreach(rootObj.SelectTokens(“Children[*]”)of type()中的var obj)
{
var metadata=obj.SelectToken(“元数据[0]”;//获取“元数据”数组中的第一个条目。
if(元数据!=null)
{
//删除整个“元数据”属性。
metadata.Parent.RemoveFromLowestPossibleParent();
//设置名称和值
变量名称=元数据。选择标记(“名称”);
var id=metadata.SelectToken(“Data.Text”);
if(name!=null&&id!=null)
obj[(字符串)名称]=(字符串)id;
//移动所有其他原子值。
foreach(metadata.SelectTokens(“…*”)of type().Where(v=>v!=id&&v!=name).ToList()中的变量值)
值。移动到(obj);
}
}
Debug.WriteLine(rootObj);
//现在将预处理的JObject反序列化到最后一个类
var root=rootObj.ToObject();
为方便起见,使用两种简单的扩展方法:
public static class JsonExtensions
{
public static void RemoveFromLowestPossibleParent(this JToken node)
{
if (node == null)
throw new ArgumentNullException();
var contained = node.AncestorsAndSelf().Where(t => t.Parent is JArray || t.Parent is JObject).FirstOrDefault();
if (contained != null)
contained.Remove();
}
public static void MoveTo(this JToken token, JObject newParent)
{
if (newParent == null)
throw new ArgumentNullException();
var toMove = token.AncestorsAndSelf().OfType<JProperty>().First(); // Throws an exception if no parent property found.
toMove.Remove();
newParent.Add(toMove);
}
}
公共静态类JsonExtensions
{
公共静态void RemoveFromLowestPossibleParent(此JToken节点)
{
if(node==null)
抛出新ArgumentNullException();
var contained=node.AncestorsAndSelf()。其中(t=>t.Parent是JArray | | t.Parent是JObject)。FirstOrDefault();
如果(包含!=null)
包含。删除();
}
公共静态void MoveTo(此JToken令牌,JObject newParent)
{
if(newParent==null)
抛出新ArgumentNullException();
var toMove=token.AncestorsAndSelf().OfType().First();//如果未找到父属性,则引发异常。
toMove.Remove();
newParent.Add(toMove);
}
}
如果您根本不想修改类型,可以使用加载和预处理JSON,如下所示:
// Load the JSON into an intermediate JObject
var rootObj = JObject.Parse(json);
// Restructure the JObject hierarchy
foreach (var obj in rootObj.SelectTokens("Children[*]").OfType<JObject>())
{
var metadata = obj.SelectToken("MetaData[0]"); // Get the first entry in the "MetaData" array.
if (metadata != null)
{
// Remove the entire "Metadata" property.
metadata.Parent.RemoveFromLowestPossibleParent();
// Set the name and value
var name = metadata.SelectToken("Name");
var id = metadata.SelectToken("Data.Text");
if (name != null && id != null)
obj[(string)name] = (string)id;
// Move all other atomic values.
foreach (var value in metadata.SelectTokens("..*").OfType<JValue>().Where(v => v != id && v != name).ToList())
value.MoveTo(obj);
}
}
Debug.WriteLine(rootObj);
// Now deserialize the preprocessed JObject to the final class
var root = rootObj.ToObject<RootObject>();
//将JSON加载到中间作业对象中
var rootObj=JObject.Parse(json);
//重新构造JObject层次结构
foreach(rootObj.SelectTokens(“Children[*]”)of type()中的var obj)
{
var metadata=obj.SelectToken(“元数据[0]”;//获取“元数据”数组中的第一个条目。
if(元数据!=null)
{
//删除整个“元数据”属性。
metadata.Parent.RemoveFromLowestPossibleParent();
//设置名称和值
变量名称=元数据。选择标记(“名称”);
var id=metadata.SelectToken(“Data.Text”);
if(name!=null&&id!=null)
obj[(字符串)名称]=(字符串)id;
//移动所有其他原子值。
foreach(metadata.SelectTokens(“…*”)of type().Where(v=>v!=id&&v!=name).ToList()中的变量值)
值。移动到(obj);
}
}
Debug.WriteLine(rootObj);
//现在将预处理的JObject反序列化到最后一个类
var root=rootObj.ToObject();
为方便起见,使用两种简单的扩展方法:
public static class JsonExtensions
{
public static void RemoveFromLowestPossibleParent(this JToken node)
{
if (node == null)
throw new ArgumentNullException();
var contained = node.AncestorsAndSelf().Where(t => t.Parent is JArray || t.Parent is JObject).FirstOrDefault();
if (contained != null)
contained.Remove();
}
public static void MoveTo(this JToken token, JObject newParent)
{
if (newParent == null)
throw new ArgumentNullException();
var toMove = token.AncestorsAndSelf().OfType<JProperty>().First(); // Throws an exception if no parent property found.
toMove.Remove();
newParent.Add(toMove);
}
}
公共静态类JsonExtensions
{
公共静态void RemoveFromLowestPossibleParent(此JToken节点)
{
if(node==null)
抛出新ArgumentNullException();
var contained=node.AncestorsAndSelf()。其中(t=>t.Parent是JArray | | t.Parent是JObject)。FirstOrDefault();
如果(包含!=null)
包含。删除();
}
公共静态void MoveTo(此JToken令牌,JObject newParent)
{
if(newParent==null)
抛出新ArgumentNullException();
var toMove=token.AncestorsAndSelf().OfType().First();//如果未找到父属性,则引发异常。
toMove.Remove();
newParent.Add(toMove);
}
}
能否显示正在序列化的C#类?另外,元数据
数组总是保证只有一个元素吗?在不发布所有代码的情况下,这些类基本上是一个树结构,与第一个示例JSON的结构相同。元数据可以有许多元素。我已经找到了一个可以接受的解决方案,为一些嵌套结构创建别名类型属性以将其展平。我本不想让底层类参与其中,但至少它只是额外的属性,几乎没有逻辑。你能展示一下你正在序列化的C#类吗?元数据
数组也总是有保证的吗