2014-09-04 17 views
5

Json'u bu şekilde seri hale getirmem gerekiyor (bu DICOM'da tanımlandığı gibidir - uluslararası bir standarttır, bu yüzden biçimi değiştiremiyorum!)Json.Net'i kullanarak veri özelliklerine bağlı olarak Json.Net kullanarak serileştirmek için bir nesne türünü nasıl seçebilirim?

{ 
.... 
"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" 
}, 

uzun listedeki her bir özelliği (!)) bir ad (yukarıdaki örnekte 0008XXXX sahiptir ve alt özellikleri "vr" ve Değerine sahiptir. Çoğu durumda, Değer basitçe bir dizi nesnedir (string veya sayı) ve bu iyi, ancak 2 özel durum için (PN ve SQ yukarıdaki gibi) özel işleme ihtiyaç duyar ve SQ durumunda aslında bir dizi tekrar üst düzey nesne (iç içe yinelemeli sonsuza kadar iç içe olabilir ...)

Neye ihtiyacım var, "vr" değerini denetlemek ve json.net 'e kullanması gereken seriyi vermek için basit bir yöntemdir. İlişkili "Değer" için - bunu yapmak için basit bir yol var mı? Tabii ki, vr, değerden önce veya sonra gelebilir (uzaktan uygulamaya bağlı olarak), işleri daha da karmaşıklaştırabilir ...

json.net'in ContractResolver ve JsonConverter mekanizmalarına baktım ama ContractResolver bana vermek istemiyor seçime izin vermek için okunan verilere erişim, ve JsonConverter türetilmiş sınıflar bana zaten benim için json.net dong (aksi takdirde çok iyi!) çoğu yeniden uygulamak zorunda bırakacak gibi görünüyor :-(

burada bazı bariz ve basit bir çözüm eksik muyum?

+0

'JObject' ne ihtiyaç vardır: İşte

var dict = JsonConvert.DeserializeObject<Dictionary<string, Node>>(json, new NodeConverter()); 

bir demo:

Yani, burada size JSON serisini nasıl olduğunu hep birlikte kravat için. Ne yazık ki, ayrıştırma ile bunun için yeterli zamanım yok. –

cevap

5

Ugh, işte özel birkullanarak bir anlam çıkarmaya mümkün olmalıdır, ancak. çalışmak için zor bir formattır. Dönüştürücünün içinde bir JObject kullanılması, ağır kaldırmanın çoğundan bizi koruyacaktır. Ama önce, verileri serileştirmek için birkaç sınıf tanımlamamız gerekiyor.

Birinci sınıf Node'u arayacağım; Bu, Value listesini ve vr'u içerir.

class Node 
{ 
    public IList Value { get; set; } 
    public string vr { get; set; } 
} 

İkinci sınıf, "PN" durumu için öğeleri tutmak için gereklidir.

class PnItem 
{ 
    public string AlphabeticName { get; set; } 
} 

Dönüştürücünün kodu aşağıdadır. Dönüştürücü, vr özelliğine bakabilir ve Value için doğru türde bir liste oluşturmak için bu bilgileri kullanabilir. "SQ" durum için bir List<Dictionary<string, Node>> deserializing olduğunu

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(); 
    } 
} 

dikkat edin. Bu, özyinelemeyi kapsar. Json.Net bir Düğüm'ü seri hale getirmeye çalıştığında, dönüştürücüye geri dönecektir. Özellik adlarının değişebileceğini (ör. "00080070", "00080090" vb.) Ele almak için Dictionary kullanıyoruz. Kökünde, aynı sebepten dolayı Dictionary<string, Node>'a da seri hale getirmeliyiz. https://dotnetfiddle.net/hsFlxU

+1

Kesinlikle harika - sadece ihtiyacım olan şey! Açıklık için dışarıda bıraktığım diğer tuhaflıkların bazılarına uyması için biraz değişiklik yapmam gerekiyordu (ör.BÜTÜN ŞEY, bir json dizisidir), bu yüzden üst düzey için aynı çift düzeyli jeneriği kullanarak sonlandırıyoruz. – medconn

+0

Ben de, daha önce birkaç tane detayın söylenmemiş olduğu hissine kapıldım! Bu çözümü ihtiyaçlarınıza uygun hale getirebildiğine sevindim. –