我正在调用在某些情况下返回带有重复节点的 JSON 的 Web 服务,提供类似于以下内容的输出:
{
"shipments": [
{
"id": "A000001",
"name": "20141208 140652",
"type": "OUTLET",
"date": "2014-12-08 14:06:52",
"status": "SENT",
"received_at": null,
"created_at": "2014-12-08 14:06:52",
"updated_at": null,
"outlet_id": "SH000064"
},
{
"id": "A000002",
"name": "20141204 122650",
"type": "SUPPLIER",
"date": "2014-12-04 12:26:50",
"outlet_id": "SH000064",
"supplier_id": null,
"status": "RECEIVED",
"outlet_id": "SH000064",
"received_at": "2014-12-04 12:28:43",
"created_at": "2014-12-04 12:26:50",
"updated_at": "2014-12-04 12:28:43"
}
]
}
我依赖服务提供商来解决这个问题,这不是他们的优先事项,所以我必须处理它。为了处理这个问题,我使用 JsonReaderWriterFactory 将 JSON 转换为 XML,然后使用以下例程从生成的 XML 中删除重复节点:
protected virtual void RemoveDuplicateChildren(XmlNode node)
{
if (node.NodeType != XmlNodeType.Element || !node.HasChildNodes)
{
return;
}
var xNode = XElement.Load(node.CreateNavigator().ReadSubtree());
var duplicateNames = new List<string>();
foreach (XmlNode child in node.ChildNodes)
{
var isBottom = this.IsBottomElement(child); // Has no XmlNodeType.Element type children
if (!isBottom)
{
this.RemoveDuplicateChildren(child);
}
else
{
var count = xNode.Elements(child.Name).Count();
if (count > 1 && !duplicateNames.Contains(child.Name))
{
duplicateNames.Add(child.Name);
}
}
}
if (duplicateNames.Count > 0)
{
foreach (var duplicate in duplicateNames)
{
var nodeList = node.SelectNodes(duplicate);
if (nodeList.Count > 1)
{
for (int i=1; i<nodeList.Count; i++)
{
node.RemoveChild(nodeList[i]);
}
}
}
}
}
我现在在一个单独的区域需要使用 DataContractJsonSerializer 将 JSON 反序列化为强类型对象,使用以下代码:
DataContractJsonSerializer serialiser = new DataContractJsonSerializer(typeof(ShipmentList));
MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(json));
var result = serialiser.ReadObject(stream);
当 JSON 包含该重复节点时,这将失败,因此我需要实现与 RemoveDuplicateChildren 方法中相同的功能,但在反序列化之前单步执行 JSON 而不是 XML 节点。我不能使用使用 JsonConvert 转换为 XML 的快速而简单的选项,使用我现有的方法删除节点,然后再转换回 JSON,因为与 XML 的转换会导致 JSON 发生变化. 是否有与 XmlNode 类提供的在 C# 中导航 JSON 层次结构的等效方法?
更新:
这个问题已经被一些评论混淆了。澄清一下,我要从 JSON 中删除的节点是在同一父级的同一级别重复的任何节点(按名称,内容无关),例如第二个“shipments”的第二个“outlet_id”上例中的项目。我需要以没有硬编码元素名称的通用方式执行此操作。上面的 RemoveDuplicateChildren 方法正是需要的,我只是想问是否有一个类可以用来在 JSON 字符串而不是 XML 字符串上执行与该方法完全相同的操作。