NewtonsoftJson 中的自定义 JSONConverter 用于序列化
Custom JSONConverter in NewtonsoftJson for Serialization
我想在 newtonsoftjson 库中编写自定义 JSON 转换器以进行序列化:
需求片段:
{
"Roles":[
{
"Role":[
{
"LEAssociateTypeId":"101",
"LEAssociateTypeId_Value":"Client/Counterparty",
"LastUpdatedDate":"2021-11-30T08:35:01",
"LegalEntityRoleStatusId":"3",
"LegalEntityRoleStatusId_Value":"Active"
},
{
"LEAssociateTypeId":"5501",
"LEAssociateTypeId_Value":"Principal",
"LastUpdatedDate":"2021-11-29T08:50:34",
"LegalEntityRoleStatusId":"3",
"LegalEntityRoleStatusId_Value":"Active"
}
]
}
]
}
收件人:
{
"Roles":[
{
"Role":{
"LEAssociateTypeId":"101",
"LEAssociateTypeId_Value":"Client/Counterparty",
"LastUpdatedDate":"2021-11-30T08:35:01",
"LegalEntityRoleStatusId":"3",
"LegalEntityRoleStatusId_Value":"Active"
}
},
{
"Role":{
"LEAssociateTypeId":"5501",
"LEAssociateTypeId_Value":"Principal",
"LastUpdatedDate":"2021-11-29T08:50:34",
"LegalEntityRoleStatusId":"3",
"LegalEntityRoleStatusId_Value":"Active"
}
}
]
}
由于角色是一个动态对象,无法为其定义相应的class。
我还查看了在线文档 Role is converted to an array as per https://www.newtonsoft.com/json/help/html/convertingjsonandxml.html
编写的源代码:
public class customconverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return true;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
JToken t = JToken.FromObject(value);
if (t.Type != JTokenType.Object)
{
t.WriteTo(writer);
}
else
{
JObject o = (JObject)t;
foreach(var a in _validcollectionList)
{
if (o[a] != null && o[a].Count() > 0)
{
var test = o[a][0];
var test1 = test["Role"];
var test2 = o[a] as JArray;
if (test1 != null && test1.Count() > 1)
{
foreach (var a1 in test1)
{
JObject obj = new JObject {
{ "Role", a1 }
};
test2.Add(obj);
}
}
test.Remove();
}
}
o.WriteTo(writer);
}
}
}
[11/12/2021] 更新:准确完整 json 就像:
{
"Message": {
"MessageInfo": {
"Guid": "a2152d96-c202-4c08-a4a7-2331a648b586",
"SourceId": "101",
},
"Roles":[
{
"Role":[
{
"LEAssociateTypeId":"101",
"LEAssociateTypeId_Value":"Client/Counterparty",
"LastUpdatedDate":"2021-11-30T08:35:01",
"LegalEntityRoleStatusId":"3",
"LegalEntityRoleStatusId_Value":"Active"
},
{
"LEAssociateTypeId":"5501",
"LEAssociateTypeId_Value":"Principal",
"LastUpdatedDate":"2021-11-29T08:50:34",
"LegalEntityRoleStatusId":"3",
"LegalEntityRoleStatusId_Value":"Active"
}
]
}
]
}
}
实体或属性的数量也是动态的,因此以上内容可能会有所不同。
已检查解决方案,下面的代码行没有角色详细信息=
var semiParsedJson = JObject.Parse(json);
只有 messageinfo 存在,所以它没有解析完整 json。
我们也不能通过自定义 json 转换器来做,因为最初的目的是通过下面的代码行将 xml 转换为 json :
XmlDocument doc = new XmlDocument();
doc.Load("XMLFile1.xml");
string jsonText = JsonConvert.SerializeXmlNode(doc, Newtonsoft.Json.Formatting.Indented);
但 newtonsoftjson 库以某种方式将同一级别的相同名称的节点分组到一个数组中,所以这就是出现此查询的原因。
请多多指教。
[12/12/2021]:示例 XML 片段:
<Message>
<MessageInfo>
<Guid>be190914-4b18-4454-96ec-67887dd4d7a7</Guid>
<SourceId>101</SourceId>
</MessageInfo>
<LegalEntities>
<LegalEntity>
<Roles>
<Role>
<LEAssociateTypeId>101</LEAssociateTypeId>
<LEAssociateTypeId_Value>Client/Counterparty</LEAssociateTypeId_Value>
<LastUpdatedDate>2021-08-07T23:05:17</LastUpdatedDate>
<LegalEntityRoleStatusId>3</LegalEntityRoleStatusId>
<LegalEntityRoleStatusId_Value>Active</LegalEntityRoleStatusId_Value>
</Role>
<Role>
<LEAssociateTypeId>6000</LEAssociateTypeId>
<LEAssociateTypeId_Value>Account Owner</LEAssociateTypeId_Value>
<LastUpdatedDate>2021-08-07T21:20:07</LastUpdatedDate>
<LegalEntityRoleStatusId>3</LegalEntityRoleStatusId>
<LegalEntityRoleStatusId_Value>Active</LegalEntityRoleStatusId_Value>
</Role>
<Role>
<LEAssociateTypeId>5003</LEAssociateTypeId>
<LEAssociateTypeId_Value>Investment Manager</LEAssociateTypeId_Value>
<LastUpdatedDate>2021-08-16T06:12:59</LastUpdatedDate>
<LegalEntityRoleStatusId>3</LegalEntityRoleStatusId>
<LegalEntityRoleStatusId_Value>Active</LegalEntityRoleStatusId_Value>
</Role>
</Roles>
</LegalEntity>
</LegalEntities>
</Message>
如果我的理解是正确的,那么你想做以下事情:
Roles
应该有两个 children 而不是一个
Role
不应该是一个集合,而是 属性
我认为进行此转换的最简单方法是通过 Linq to Json
static void Main(string[] args)
{
var json = "...";
var semiParsedJson = JObject.Parse(json);
Console.WriteLine(TranformJson(semiParsedJson));
}
static string TranformJson(JObject semiParsed)
{
if (!semiParsed.TryGetValue("Roles", out var roles))
return null;
if (roles is not JArray rolesArray)
return null;
var firstRole = (JObject)rolesArray.First();
if (!firstRole.TryGetValue("Role", out var role))
return null;
if (role is not JArray roleArray)
return null;
var newStructure = new
{
Roles = roleArray.Children()
.Select(role => new { Role = role })
};
return JsonConvert.SerializeObject(newStructure);
}
- 我们将 json 解析为
JObject
以帮助我们检索特定属性/集合
- 我们尝试检索
Roles
属性 如果它不存在那么我们 return null
- 如果它存在,那么我们检查它是否是一个集合。我在这里使用了 C# 9 的新
is not
特性
- 如果它不是集合那么我们 return 和
null
- 如果它是一个集合,那么我们从中检索第一个元素
- 我们执行相同的步骤 (2-4) 来检索
Role
集合
- 我们创建一个新的匿名 object 以所需方式表示数据
- 我们也对最内部的 object 进行了一些转换
- 最后我们将新构建的object序列化为字符串得到想要的输出
- 尽情享受吧! :)
我留下另一个 post 因为 OP 的问题与原始版本相比发生了很大变化。
只是为了确保我们的理解是一样的:
- 您想使用
JsonConvert.SerializeXNode
将 xml 转换为 json
- 默认情况下此方法不能优雅地处理数组
- 您还想更改
Role
节点的表示,使其周围有一个包装器对象
让我们一个一个解决问题
XML 节点到 Json 数组
为了将 LegalEntities
和 Roles
视为数组,您需要向这些 xml 节点添加自定义属性:json:Array = "true"
.
这个 json
命名空间必须像这样在 xml 中定义:xmlns:json="http://james.newtonking.com/projects/json"
因此,您需要将 xml 修改为此(手动或通过 System.Xml
/ System.Xml.Linq
):
<Message xmlns:json="http://james.newtonking.com/projects/json">
<MessageInfo>
<Guid>be190914-4b18-4454-96ec-67887dd4d7a7</Guid>
<SourceId>101</SourceId>
</MessageInfo>
<LegalEntities json:Array="true">
<LegalEntity>
<Roles json:Array="true">
<Role>
<LEAssociateTypeId>101</LEAssociateTypeId>
<LEAssociateTypeId_Value>Client/Counterparty</LEAssociateTypeId_Value>
<LastUpdatedDate>2021-08-07T23:05:17</LastUpdatedDate>
<LegalEntityRoleStatusId>3</LegalEntityRoleStatusId>
<LegalEntityRoleStatusId_Value>Active</LegalEntityRoleStatusId_Value>
</Role>
<Role>
<LEAssociateTypeId>6000</LEAssociateTypeId>
<LEAssociateTypeId_Value>Account Owner</LEAssociateTypeId_Value>
<LastUpdatedDate>2021-08-07T21:20:07</LastUpdatedDate>
<LegalEntityRoleStatusId>3</LegalEntityRoleStatusId>
<LegalEntityRoleStatusId_Value>Active</LegalEntityRoleStatusId_Value>
</Role>
<Role>
<LEAssociateTypeId>5003</LEAssociateTypeId>
<LEAssociateTypeId_Value>Investment Manager</LEAssociateTypeId_Value>
<LastUpdatedDate>2021-08-16T06:12:59</LastUpdatedDate>
<LegalEntityRoleStatusId>3</LegalEntityRoleStatusId>
<LegalEntityRoleStatusId_Value>Active</LegalEntityRoleStatusId_Value>
</Role>
</Roles>
</LegalEntity>
</LegalEntities>
</Message>
现在,如果您将其传递给 SerializeXNode
,那么您将得到以下内容 json:
{
"Message":{
"MessageInfo":{
"Guid":"be190914-4b18-4454-96ec-67887dd4d7a7",
"SourceId":"101"
},
"LegalEntities":[
{
"LegalEntity":{
"Roles":[
{
"Role":[
{
"LEAssociateTypeId":"101",
"LEAssociateTypeId_Value":"Client/Counterparty",
"LastUpdatedDate":"2021-08-07T23:05:17",
"LegalEntityRoleStatusId":"3",
"LegalEntityRoleStatusId_Value":"Active"
},
{
"LEAssociateTypeId":"6000",
"LEAssociateTypeId_Value":"Account Owner",
"LastUpdatedDate":"2021-08-07T21:20:07",
"LegalEntityRoleStatusId":"3",
"LegalEntityRoleStatusId_Value":"Active"
},
{
"LEAssociateTypeId":"5003",
"LEAssociateTypeId_Value":"Investment Manager",
"LastUpdatedDate":"2021-08-16T06:12:59",
"LegalEntityRoleStatusId":"3",
"LegalEntityRoleStatusId_Value":"Active"
}
]
}
]
}
}
]
}
}
变换Role
个节点
为了能够执行一些转换,您需要通过 SelectToken
方法检索适当的节点
var doc = XDocument.Parse(xml);
var json = JsonConvert.SerializeXNode(doc);
var root = JObject.Parse(json);
var roles = root.SelectToken("$.Message.LegalEntities[0].LegalEntity.Roles") as JArray;
if (roles == null) return;
var role = roles.First().SelectToken("$.Role") as JArray;
if (roles == null) return;
- 第一个
SelectToken
检索到 Roles
集合
- 第二个
SelectToken
检索了 Role
集合
现在,让我们进行转换:
var roleNodes = new List<JObject>();
foreach (var roleNode in role)
{
roleNodes.Add(new JObject(new JProperty("Role", roleNode)));
}
这里我们遍历 Role
集合,我们正在围绕它创建一个包装器对象,它有一个名为 Role 的 属性。
最后我们必须用新创建的 JObject
替换 Roles
集合。这可以通过以下简单命令实现:
roles.ReplaceAll(roleNodes);
为了完整起见,这里是完整的代码:
var xml = File.ReadAllText("sample.xml");
var doc = XDocument.Parse(xml);
var json = JsonConvert.SerializeXNode(doc);
var root = JObject.Parse(json);
var roles = root.SelectToken("$.Message.LegalEntities[0].LegalEntity.Roles") as JArray;
if (roles == null) return;
var role = roles.First().SelectToken("$.Role") as JArray;
if (roles == null) return;
var roleNodes = new List<JObject>();
foreach (var roleNode in role)
{
roleNodes.Add(new JObject(new JProperty("Role", roleNode)));
}
roles.ReplaceAll(roleNodes);
Console.WriteLine(root);
和发出的输出:
{
"Message": {
"MessageInfo": {
"Guid": "be190914-4b18-4454-96ec-67887dd4d7a7",
"SourceId": "101"
},
"LegalEntities": [
{
"LegalEntity": {
"Roles": [
{
"Role": {
"LEAssociateTypeId": "101",
"LEAssociateTypeId_Value": "Client/Counterparty",
"LastUpdatedDate": "2021-08-07T23:05:17",
"LegalEntityRoleStatusId": "3",
"LegalEntityRoleStatusId_Value": "Active"
}
},
{
"Role": {
"LEAssociateTypeId": "6000",
"LEAssociateTypeId_Value": "Account Owner",
"LastUpdatedDate": "2021-08-07T21:20:07",
"LegalEntityRoleStatusId": "3",
"LegalEntityRoleStatusId_Value": "Active"
}
},
{
"Role": {
"LEAssociateTypeId": "5003",
"LEAssociateTypeId_Value": "Investment Manager",
"LastUpdatedDate": "2021-08-16T06:12:59",
"LegalEntityRoleStatusId": "3",
"LegalEntityRoleStatusId_Value": "Active"
}
}
]
}
}
]
}
}
我想在 newtonsoftjson 库中编写自定义 JSON 转换器以进行序列化:
需求片段:
{
"Roles":[
{
"Role":[
{
"LEAssociateTypeId":"101",
"LEAssociateTypeId_Value":"Client/Counterparty",
"LastUpdatedDate":"2021-11-30T08:35:01",
"LegalEntityRoleStatusId":"3",
"LegalEntityRoleStatusId_Value":"Active"
},
{
"LEAssociateTypeId":"5501",
"LEAssociateTypeId_Value":"Principal",
"LastUpdatedDate":"2021-11-29T08:50:34",
"LegalEntityRoleStatusId":"3",
"LegalEntityRoleStatusId_Value":"Active"
}
]
}
]
}
收件人:
{
"Roles":[
{
"Role":{
"LEAssociateTypeId":"101",
"LEAssociateTypeId_Value":"Client/Counterparty",
"LastUpdatedDate":"2021-11-30T08:35:01",
"LegalEntityRoleStatusId":"3",
"LegalEntityRoleStatusId_Value":"Active"
}
},
{
"Role":{
"LEAssociateTypeId":"5501",
"LEAssociateTypeId_Value":"Principal",
"LastUpdatedDate":"2021-11-29T08:50:34",
"LegalEntityRoleStatusId":"3",
"LegalEntityRoleStatusId_Value":"Active"
}
}
]
}
由于角色是一个动态对象,无法为其定义相应的class。
我还查看了在线文档 Role is converted to an array as per https://www.newtonsoft.com/json/help/html/convertingjsonandxml.html
编写的源代码:
public class customconverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return true;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
JToken t = JToken.FromObject(value);
if (t.Type != JTokenType.Object)
{
t.WriteTo(writer);
}
else
{
JObject o = (JObject)t;
foreach(var a in _validcollectionList)
{
if (o[a] != null && o[a].Count() > 0)
{
var test = o[a][0];
var test1 = test["Role"];
var test2 = o[a] as JArray;
if (test1 != null && test1.Count() > 1)
{
foreach (var a1 in test1)
{
JObject obj = new JObject {
{ "Role", a1 }
};
test2.Add(obj);
}
}
test.Remove();
}
}
o.WriteTo(writer);
}
}
}
[11/12/2021] 更新:准确完整 json 就像:
{
"Message": {
"MessageInfo": {
"Guid": "a2152d96-c202-4c08-a4a7-2331a648b586",
"SourceId": "101",
},
"Roles":[
{
"Role":[
{
"LEAssociateTypeId":"101",
"LEAssociateTypeId_Value":"Client/Counterparty",
"LastUpdatedDate":"2021-11-30T08:35:01",
"LegalEntityRoleStatusId":"3",
"LegalEntityRoleStatusId_Value":"Active"
},
{
"LEAssociateTypeId":"5501",
"LEAssociateTypeId_Value":"Principal",
"LastUpdatedDate":"2021-11-29T08:50:34",
"LegalEntityRoleStatusId":"3",
"LegalEntityRoleStatusId_Value":"Active"
}
]
}
]
}
}
实体或属性的数量也是动态的,因此以上内容可能会有所不同。
已检查解决方案,下面的代码行没有角色详细信息=
var semiParsedJson = JObject.Parse(json);
只有 messageinfo 存在,所以它没有解析完整 json。
我们也不能通过自定义 json 转换器来做,因为最初的目的是通过下面的代码行将 xml 转换为 json :
XmlDocument doc = new XmlDocument();
doc.Load("XMLFile1.xml");
string jsonText = JsonConvert.SerializeXmlNode(doc, Newtonsoft.Json.Formatting.Indented);
但 newtonsoftjson 库以某种方式将同一级别的相同名称的节点分组到一个数组中,所以这就是出现此查询的原因。
请多多指教。
[12/12/2021]:示例 XML 片段:
<Message>
<MessageInfo>
<Guid>be190914-4b18-4454-96ec-67887dd4d7a7</Guid>
<SourceId>101</SourceId>
</MessageInfo>
<LegalEntities>
<LegalEntity>
<Roles>
<Role>
<LEAssociateTypeId>101</LEAssociateTypeId>
<LEAssociateTypeId_Value>Client/Counterparty</LEAssociateTypeId_Value>
<LastUpdatedDate>2021-08-07T23:05:17</LastUpdatedDate>
<LegalEntityRoleStatusId>3</LegalEntityRoleStatusId>
<LegalEntityRoleStatusId_Value>Active</LegalEntityRoleStatusId_Value>
</Role>
<Role>
<LEAssociateTypeId>6000</LEAssociateTypeId>
<LEAssociateTypeId_Value>Account Owner</LEAssociateTypeId_Value>
<LastUpdatedDate>2021-08-07T21:20:07</LastUpdatedDate>
<LegalEntityRoleStatusId>3</LegalEntityRoleStatusId>
<LegalEntityRoleStatusId_Value>Active</LegalEntityRoleStatusId_Value>
</Role>
<Role>
<LEAssociateTypeId>5003</LEAssociateTypeId>
<LEAssociateTypeId_Value>Investment Manager</LEAssociateTypeId_Value>
<LastUpdatedDate>2021-08-16T06:12:59</LastUpdatedDate>
<LegalEntityRoleStatusId>3</LegalEntityRoleStatusId>
<LegalEntityRoleStatusId_Value>Active</LegalEntityRoleStatusId_Value>
</Role>
</Roles>
</LegalEntity>
</LegalEntities>
</Message>
如果我的理解是正确的,那么你想做以下事情:
Roles
应该有两个 children 而不是一个Role
不应该是一个集合,而是 属性
我认为进行此转换的最简单方法是通过 Linq to Json
static void Main(string[] args)
{
var json = "...";
var semiParsedJson = JObject.Parse(json);
Console.WriteLine(TranformJson(semiParsedJson));
}
static string TranformJson(JObject semiParsed)
{
if (!semiParsed.TryGetValue("Roles", out var roles))
return null;
if (roles is not JArray rolesArray)
return null;
var firstRole = (JObject)rolesArray.First();
if (!firstRole.TryGetValue("Role", out var role))
return null;
if (role is not JArray roleArray)
return null;
var newStructure = new
{
Roles = roleArray.Children()
.Select(role => new { Role = role })
};
return JsonConvert.SerializeObject(newStructure);
}
- 我们将 json 解析为
JObject
以帮助我们检索特定属性/集合 - 我们尝试检索
Roles
属性 如果它不存在那么我们 returnnull
- 如果它存在,那么我们检查它是否是一个集合。我在这里使用了 C# 9 的新
is not
特性 - 如果它不是集合那么我们 return 和
null
- 如果它是一个集合,那么我们从中检索第一个元素
- 我们执行相同的步骤 (2-4) 来检索
Role
集合 - 我们创建一个新的匿名 object 以所需方式表示数据
- 我们也对最内部的 object 进行了一些转换
- 最后我们将新构建的object序列化为字符串得到想要的输出
- 尽情享受吧! :)
我留下另一个 post 因为 OP 的问题与原始版本相比发生了很大变化。
只是为了确保我们的理解是一样的:
- 您想使用
JsonConvert.SerializeXNode
将 xml 转换为 json - 默认情况下此方法不能优雅地处理数组
- 您还想更改
Role
节点的表示,使其周围有一个包装器对象
让我们一个一个解决问题
XML 节点到 Json 数组
为了将 LegalEntities
和 Roles
视为数组,您需要向这些 xml 节点添加自定义属性:json:Array = "true"
.
这个 json
命名空间必须像这样在 xml 中定义:xmlns:json="http://james.newtonking.com/projects/json"
因此,您需要将 xml 修改为此(手动或通过 System.Xml
/ System.Xml.Linq
):
<Message xmlns:json="http://james.newtonking.com/projects/json">
<MessageInfo>
<Guid>be190914-4b18-4454-96ec-67887dd4d7a7</Guid>
<SourceId>101</SourceId>
</MessageInfo>
<LegalEntities json:Array="true">
<LegalEntity>
<Roles json:Array="true">
<Role>
<LEAssociateTypeId>101</LEAssociateTypeId>
<LEAssociateTypeId_Value>Client/Counterparty</LEAssociateTypeId_Value>
<LastUpdatedDate>2021-08-07T23:05:17</LastUpdatedDate>
<LegalEntityRoleStatusId>3</LegalEntityRoleStatusId>
<LegalEntityRoleStatusId_Value>Active</LegalEntityRoleStatusId_Value>
</Role>
<Role>
<LEAssociateTypeId>6000</LEAssociateTypeId>
<LEAssociateTypeId_Value>Account Owner</LEAssociateTypeId_Value>
<LastUpdatedDate>2021-08-07T21:20:07</LastUpdatedDate>
<LegalEntityRoleStatusId>3</LegalEntityRoleStatusId>
<LegalEntityRoleStatusId_Value>Active</LegalEntityRoleStatusId_Value>
</Role>
<Role>
<LEAssociateTypeId>5003</LEAssociateTypeId>
<LEAssociateTypeId_Value>Investment Manager</LEAssociateTypeId_Value>
<LastUpdatedDate>2021-08-16T06:12:59</LastUpdatedDate>
<LegalEntityRoleStatusId>3</LegalEntityRoleStatusId>
<LegalEntityRoleStatusId_Value>Active</LegalEntityRoleStatusId_Value>
</Role>
</Roles>
</LegalEntity>
</LegalEntities>
</Message>
现在,如果您将其传递给 SerializeXNode
,那么您将得到以下内容 json:
{
"Message":{
"MessageInfo":{
"Guid":"be190914-4b18-4454-96ec-67887dd4d7a7",
"SourceId":"101"
},
"LegalEntities":[
{
"LegalEntity":{
"Roles":[
{
"Role":[
{
"LEAssociateTypeId":"101",
"LEAssociateTypeId_Value":"Client/Counterparty",
"LastUpdatedDate":"2021-08-07T23:05:17",
"LegalEntityRoleStatusId":"3",
"LegalEntityRoleStatusId_Value":"Active"
},
{
"LEAssociateTypeId":"6000",
"LEAssociateTypeId_Value":"Account Owner",
"LastUpdatedDate":"2021-08-07T21:20:07",
"LegalEntityRoleStatusId":"3",
"LegalEntityRoleStatusId_Value":"Active"
},
{
"LEAssociateTypeId":"5003",
"LEAssociateTypeId_Value":"Investment Manager",
"LastUpdatedDate":"2021-08-16T06:12:59",
"LegalEntityRoleStatusId":"3",
"LegalEntityRoleStatusId_Value":"Active"
}
]
}
]
}
}
]
}
}
变换Role
个节点
为了能够执行一些转换,您需要通过 SelectToken
方法检索适当的节点
var doc = XDocument.Parse(xml);
var json = JsonConvert.SerializeXNode(doc);
var root = JObject.Parse(json);
var roles = root.SelectToken("$.Message.LegalEntities[0].LegalEntity.Roles") as JArray;
if (roles == null) return;
var role = roles.First().SelectToken("$.Role") as JArray;
if (roles == null) return;
- 第一个
SelectToken
检索到Roles
集合 - 第二个
SelectToken
检索了Role
集合
现在,让我们进行转换:
var roleNodes = new List<JObject>();
foreach (var roleNode in role)
{
roleNodes.Add(new JObject(new JProperty("Role", roleNode)));
}
这里我们遍历 Role
集合,我们正在围绕它创建一个包装器对象,它有一个名为 Role 的 属性。
最后我们必须用新创建的 JObject
替换 Roles
集合。这可以通过以下简单命令实现:
roles.ReplaceAll(roleNodes);
为了完整起见,这里是完整的代码:
var xml = File.ReadAllText("sample.xml");
var doc = XDocument.Parse(xml);
var json = JsonConvert.SerializeXNode(doc);
var root = JObject.Parse(json);
var roles = root.SelectToken("$.Message.LegalEntities[0].LegalEntity.Roles") as JArray;
if (roles == null) return;
var role = roles.First().SelectToken("$.Role") as JArray;
if (roles == null) return;
var roleNodes = new List<JObject>();
foreach (var roleNode in role)
{
roleNodes.Add(new JObject(new JProperty("Role", roleNode)));
}
roles.ReplaceAll(roleNodes);
Console.WriteLine(root);
和发出的输出:
{
"Message": {
"MessageInfo": {
"Guid": "be190914-4b18-4454-96ec-67887dd4d7a7",
"SourceId": "101"
},
"LegalEntities": [
{
"LegalEntity": {
"Roles": [
{
"Role": {
"LEAssociateTypeId": "101",
"LEAssociateTypeId_Value": "Client/Counterparty",
"LastUpdatedDate": "2021-08-07T23:05:17",
"LegalEntityRoleStatusId": "3",
"LegalEntityRoleStatusId_Value": "Active"
}
},
{
"Role": {
"LEAssociateTypeId": "6000",
"LEAssociateTypeId_Value": "Account Owner",
"LastUpdatedDate": "2021-08-07T21:20:07",
"LegalEntityRoleStatusId": "3",
"LegalEntityRoleStatusId_Value": "Active"
}
},
{
"Role": {
"LEAssociateTypeId": "5003",
"LEAssociateTypeId_Value": "Investment Manager",
"LastUpdatedDate": "2021-08-16T06:12:59",
"LegalEntityRoleStatusId": "3",
"LegalEntityRoleStatusId_Value": "Active"
}
}
]
}
}
]
}
}