2015-03-02 17 views
5

Angenommen, ich die folgende Klasse habe -Deserialisieren öffentliches Eigentum mit nicht-öffentlichen Setter in json.net

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

json.net benutzen, ich bin in der Lage, die Art mit P1 Eigenschaft serialisiert werden. Während der Deserialisierung wird P1 jedoch nicht festgelegt. Ohne die Klasse A zu ändern, gibt es eine eingebaute Methode, um damit umzugehen? In meinem Fall verwende ich eine Klasse aus einer anderen Assembly und kann sie nicht ändern.

Antwort

5

Ja, Sie können eine benutzerdefinierte ContractResolver verwenden, um die interne Eigenschaft in Json.Net schreibbar zu machen. Hier ist der Code, den Sie müssten:

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

Um den Resolver zu verwenden, erstellen Sie eine Instanz von JsonSerializerSettings und legen Sie seine ContractResolver Eigenschaft auf eine neue Instanz des benutzerdefinierten Resolver. Übergeben Sie dann die Einstellungen an 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); 
    } 
} 

Ausgang:

42 

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

+1

BrianRogers folgte Ihrem Beispiel, entfernte aber die Bedingung, um den Typ und die Eigenschaft zu überprüfen, die alle beschreibbar sein sollten. Es funktionierte. Vielen Dank :) – Riga

0

Das ist meine Lösung ist in allgemeinerer Fall zu behandeln:

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

Dann testen Sie es mit gegen diese Klasse:

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

Nach einigem Experimentieren, ich habe festgestellt, dass eine Eigenschaft deserialised richtig, wenn Sie Ihre Immobilie dekorieren mit:

[JsonProperty(DefaultValueHandling = DefaultValueHandling.Include)] 

die Klasse Anwendung in der ursprünglichen Frage:

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