med*_*onn 5 c# recursion serialization json.net json-deserialization
我需要像这样反序列化json(它是在DICOM中定义的 - 一个国际标准,所以我不能改变格式!)
{
....
"00080060": {
"Value": [
"US"
],
"vr": "CS"
},
"00080070": {
"Value": [
"ACME Products"
],
"vr": "LO"
},
"00080090": {
"Value": [
{
"AlphabeticName": "Better^Make^U.^MD"
}
],
"vr": "PN"
},
"00081110": {
"Value": [
{
"00080008": {
"Value": [
"XX_0",
"OIU",
null,
"PPP"
],
"vr": "CS"
}
},
{},
{
"00080008": {
"Value": [
"XX_2",
"OIU",
null,
"PPP"
],
"vr": "CS"
}
}
],
"vr": "SQ"
},
Run Code Online (Sandbox Code Playgroud)
每个属性(在长列表中!)都有一个名称(上例中为0008XXXX),并具有子属性"vr"和Value.在大多数情况下,Value只是一个对象数组(字符串或数字),这很好,但对于2个特殊情况(如上所述的PN和SQ),它需要特殊处理,而在SQ的情况下,它实际上是一个数组顶级对象再次(可以无限递归地嵌套...)
所以 - 我需要的是一个简单的方法,在反序列化期间检查"vr"值并为json.net提供它应该用于相关"值"的类型 - 是否有一种简单的方法可以做到这一点?当然,vr可以在Value之前或之后(取决于远程实现)可能会使事情进一步复杂化......
我查看了json.net的ContractResolver和JsonConverter机制,但是ContractResolver似乎没有让我访问正在读取的数据以便允许做出选择,而JsonConverter派生类似乎让我不得不重新实现大多数什么json.net是东(否则很好!)对我来说已经:-(
我在这里错过了一些明显而简单的解决方案吗
呃,这是一个很难处理的格式.但是,应该可以使用自定义来理解它JsonConverter.使用JObject转换器内部将保护我们免受大部分繁重的工作.但首先,我们需要定义几个类来将数据反序列化.
我要打的第一堂课Node; 这将包含Value列表和vr.
class Node
{
public IList Value { get; set; }
public string vr { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
持有"PN"案件的物品需要第二类.
class PnItem
{
public string AlphabeticName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
这是转换器的代码.转换器可以查看vr属性并使用该信息为其创建正确的列表类型Value.
class NodeConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(Node));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jo = JObject.Load(reader);
Node node = new Node();
node.vr = (string)jo["vr"];
if (node.vr == "PN")
{
node.Value = jo["Value"].ToObject<List<PnItem>>(serializer);
}
else if (node.vr == "SQ")
{
node.Value = jo["Value"].ToObject<List<Dictionary<string, Node>>>(serializer);
}
else
{
node.Value = jo["Value"].ToObject<List<string>>(serializer);
}
return node;
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,对于"SQ"情况,我们反序列化a List<Dictionary<string, Node>>.这涵盖了递归结构.每当Json.Net尝试反序列化节点时,它都会回调到转换器.我们使用a Dictionary来处理属性名称可以变化的事实(例如"00080070","00080090"等).从根本上说,Dictionary<string, Node>出于同样的原因,我们也必须反序列化为a .
因此,要将它们组合在一起,以下是对反序列化JSON的方法:
var dict = JsonConvert.DeserializeObject<Dictionary<string, Node>>(json,
new NodeConverter());
Run Code Online (Sandbox Code Playgroud)
这是一个演示:https://dotnetfiddle.net/hsFlxU