2013-10-22 10 views
5

Gerçek koduma kolay bir örnek var. Letters'dan türetilen JS123'e serileştirilmeli ve TestClass sınıfının nesnesini geri seri hale getirmem gerekiyor. Her iki sınıf da parametreli kurucuya sahiptir. Nesne seri hale getirilemedi, çünkü 'Toplama sabit bir boyuttaydı.'

public class TestClass : Letters 
    { 
     public string[] Names { get; private set; } 

     public TestClass(string[] names) 
      : base(names) 
      // : base(new [] { "A", "B", }) 
      // : base(names.Select(a => a.Substring(0, 1)).ToArray()) 
     { 
      Names = names; 
     } 
    } 

    public abstract class Letters 
    { 
     public string[] FirstLetters { get; private set; } 

     protected Letters(string[] letters) 
     { 
      FirstLetters = letters; 
     } 
    } 

Nesne TestClass ait

NotSupportedException mesajı Koleksiyonu ile sabit boyutta idi atmak olduğunu geçerli JSON tefrika edilir ama bunun serisini çalıştığınızda geri nesneye.

Burada aksi takdirde kurucusunu çağırmak için bilmiyor, benim test onları serisini amacıyla bir parametresiz yapıcı olması tüm sınıfları ihtiyacı Json.Net

[Fact] 
    public void JsonNamesTest() 
    { 
     var expected = new TestClass(new [] { "Alex", "Peter", "John", }); 

     var serialized = JsonConvert.SerializeObject(expected); 
     Console.WriteLine(serialized); 

     Assert.False(string.IsNullOrWhiteSpace(serialized)); 

     var actual = JsonConvert.DeserializeObject<TestClass>(serialized); 

     AssertEx.PrimitivePropertiesEqual(expected, actual); 
    } 
+0

sahip tek kamu yapıcısı olan 'listesi nedir? –

+0

Çünkü var olan ve değişmesi kolay olan sınıfları seri hale getirmeye ve seri hale getirmeye ihtiyacım var. Tüm sınıfların yeniden yazılması son olasılıktır. – Rudis

cevap

6

olduğunu. Sınıflarınızı değiştirmeden bunu aşmanın bir yolu, nesne örneğini JSON'dan oluşturacak özel bir JsonConverter yapmaktır. Örneğin:

class TestClassConverter : JsonConverter 
{ 
    public override bool CanConvert(Type objectType) 
    { 
     return typeof(TestClass) == objectType; 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     JObject jo = JObject.Load(reader); 
     string[] names = jo["Names"].ToObject<string[]>(); 
     return new TestClass(names); 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     serializer.Serialize(writer, value); 
    } 
} 

Sonra, bu gibi sınıf serisini ve çalışması gerekir:

var actual = JsonConvert.DeserializeObject<TestClass>(serialized, new TestClassConverter()); 
1

teşekkürler, çalışıyor! Örneğimde daha genel kullanım için kodunuzu değiştirdim.

herhalde

  • tefrika parametreler yapıcı parametreleri aynı ada (görmezden harf) yerine Array kullanmanız gerekiyor Neden

    public class ParametersContructorConverter : JsonConverter 
    { 
        public override bool CanConvert(Type objectType) 
        { 
         return typeof(Letters).IsAssignableFrom(objectType); 
        } 
    
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
        { 
         var jo = JObject.Load(reader); 
         var contructor = objectType.GetConstructors().FirstOrDefault(); 
    
         if (contructor == null) 
         { 
          return serializer.Deserialize(reader); 
         } 
    
         var parameters = contructor.GetParameters(); 
         var values = parameters.Select(p => jo.GetValue(p.Name, StringComparison.InvariantCultureIgnoreCase).ToObject(p.ParameterType)).ToArray(); 
    
         return contructor.Invoke(values); 
        } 
    
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
        { 
         serializer.Serialize(writer, value); 
        } 
    }