2015-03-02 20 views
5

Supponiamo che io ho la seguente classe -deserializzazione proprietà pubblica con il setter non pubblica in json.net

public class A 
{   
    public int P1 { get; internal set; } 
} 

Utilizzando json.net, sono in grado di serializzare il tipo con la proprietà P1. Tuttavia, durante la deserializzazione, P1 non è impostato. Senza modificare la classe A, esiste un modo per gestire questo? Nel mio caso, sto usando una classe da un assembly diverso e non posso modificarla.

risposta

5

Sì, è possibile utilizzare uno ContractResolver personalizzato per rendere scrivibile la proprietà interna su Json.Net. Ecco il codice si avrebbe bisogno:

class CustomResolver : DefaultContractResolver 
{ 
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) 
    { 
     JsonProperty prop = base.CreateProperty(member, memberSerialization); 

     if (member.DeclaringType == typeof(A) && prop.PropertyName == "P1") 
     { 
      prop.Writable = true; 
     } 

     return prop; 
    } 
} 

Per utilizzare il resolver, creare un'istanza di JsonSerializerSettings e impostarne la proprietà ContractResolver a una nuova istanza del resolver personalizzato. Quindi, passare le impostazioni a JsonConvert.DeserializeObject<T>().

Demo:

class Program 
{ 
    static void Main(string[] args) 
    { 
     string json = @"{ ""P1"" : ""42"" }"; 

     JsonSerializerSettings settings = new JsonSerializerSettings(); 
     settings.ContractResolver = new CustomResolver(); 

     A a = JsonConvert.DeserializeObject<A>(json, settings); 

     Console.WriteLine(a.P1); 
    } 
} 

uscita:

42 

Fiddle: https://dotnetfiddle.net/1fw2lC

+1

BrianRogers ha seguito il tuo esempio ma ha rimosso la condizione per controllare il tipo e la proprietà come volevano che tutti fossero scrivibili. Ha funzionato. Grazie :) – Riga

0

Questa è la mia soluzione per gestire in caso più generale:

class CustomResolver : DefaultContractResolver 
{ 
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) 
    { 
     JsonProperty result = base.CreateProperty(member, memberSerialization); 

     var propInfo = member as PropertyInfo; 
     result.Writable |= propInfo != null 
      && propInfo.CanWrite 
      && !propInfo.IsPrivate; 

     return result; 
    } 
} 

Wit h Classe CInternalSetter:

class CInternalSetter 
{ 
    public CInternalSetter() 
    { 
     LoggedEmployeeId3 = 10; 
    } 
    public int LoggedEmployeeId { get; set; } 
    public int LoggedEmployeeId2 { get; internal set; } 
    public int LoggedEmployeeId3 { get; } 
    public override string ToString() 
    { 
     return JsonConvert.SerializeObject(this, Formatting.Indented); 
    } 
} 

Poi prova con contro questa classe:

JsonSerializerSettings settings = new JsonSerializerSettings(); 
settings.ContractResolver = new CustomResolver(); 

var c = new CInternalSetter() 
{ 
    LoggedEmployeeId = 1, 
    LoggedEmployeeId2 = 2 
}; 

var cString = JsonConvert.SerializeObject(c); 

Console.WriteLine(cString); 
Console.WriteLine(JsonConvert.DeserializeObject<CInternalSetter>(cString).ToString()); 
Console.WriteLine("-------------------------------------------"); 
Console.WriteLine(JsonConvert.DeserializeObject<CInternalSetter>(cString, settings).ToString()); 
1

Dopo alcuni esperimenti, ho trovato che una proprietà è deserialised correttamente se si decorare la vostra proprietà con:

[JsonProperty(DefaultValueHandling = DefaultValueHandling.Include)] 

Applicando alla classe nella domanda iniziale:

public class A 
{ 
    [JsonProperty(DefaultValueHandling = DefaultValueHandling.Include)]   
    public int P1 { get; internal set; } 
} 
Problemi correlati