2010-11-14 15 views
6

Non ho visto molte informazioni su Json.NET che supporta la deserializzazione degli oggetti con i campi readonly. Osservo che gli attributi .NET DataContract e DataMember consentono di compilare i campi readonly durante la deserializzazione, ma Json.NET non sembra supportarlo, almeno dal comportamento che sto vedendo.Json.NET può popolare campi di sola lettura in una classe?

risposta

-2

afai può vedere cambiare un campo in readonly risultati in un valore null dopo la deserializzazione. Ho avuto un esempio funzionante per un'altra domanda (modificata come mostrato sotto), e questo è il comportamento che vedo.

public class NameAndId 
{ 
    public string name; 
    public int id; 
} 

public class Data 
{ 
    public NameAndId[] data; 
} 

public class Target 
{ 
    public string id; 
    public readonly NameAndId from; 
    public DateTime updated_time; 
    public readonly string message; 
    public Data likes; 
} 

public class Program 
{ 
    static void Main(string[] args) 
    { 
     string json = File.ReadAllText(@"c:\temp\json.txt"); 
     Target newTarget = JsonConvert.DeserializeObject<Target>(json); 
    } 
} 
+0

Sì, è lo stesso comportamento che vedo. Sfortunatamente, questo insieme alle restrizioni del costruttore sugli oggetti serializzati è per me il rompicapo di Json.NET. :( –

+0

La mia ipotesi è che le classi incorporate .Net abbiano accesso privilegiato a quei campi che non sono disponibili per la libreria di terze parti. –

+0

Non è diverso dall'impostare qualsiasi altro campo con il riflesso, quindi è fattibile e ho archiviato un richiesta di funzionalità sul tracker di errori Json.NET – asgerhallas

9

Non è la soluzione più elegante, ma è possibile estendere il DefaultConstractResolver per farlo:

public class ContractResolver : DefaultContractResolver 
{ 
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) 
    { 
     var property = base.CreateProperty(member, memberSerialization); 
     property.Writable = CanSetMemberValue(member, true); 
     return property; 
    } 

    public static bool CanSetMemberValue(MemberInfo member, bool nonPublic) 
    { 
     switch (member.MemberType) 
     { 
      case MemberTypes.Field: 
       var fieldInfo = (FieldInfo)member; 

       return nonPublic || fieldInfo.IsPublic; 
      case MemberTypes.Property: 
       var propertyInfo = (PropertyInfo)member; 

       if (!propertyInfo.CanWrite) 
        return false; 
       if (nonPublic) 
        return true; 
       return (propertyInfo.GetSetMethod(nonPublic) != null); 
      default: 
       return false; 
     } 
    } 
} 

Ho solo rimuovere un po 'di controllo dal metodo CanSetMemberValue. Sfortunatamente non è né virtuale né un metodo di istanza, quindi ho dovuto scavalcare anche CreateProperty.

1

Questo può essere fatto ora. Dichiarare le proprietà utilizzando l'attributo JsonProperty, e garantire che essi hanno una serie protetta dichiarato:

[JsonProperty("Name")] public string Name {get; protected set;} 

Questo non ha funzionato per me quando si utilizza solo un get, ma funziona perfettamente con il protected set.

Problemi correlati