Özel ayarlayıcıları idare edecek bir özellik olduğunu biliyorum ama bu davranışı varsayılan olarak istiyorum, bunu başarmanın bir yolu var mı? Kaynakta değişiklik yapmak dışında. Bunun için bir ayar olsaydı harika olurdu.
Yanıtlar:
Buraya, Json.NET'in seriyi kaldırırken salt okunur bir özelliği doldurmasını sağlayan gerçek niteliği aramak için geldim ve bu basitçe [JsonProperty], örneğin:
[JsonProperty]
public Guid? ClientId { get; private set; }
Mülkünüzle eşleşen bir parametreye sahip bir yapıcı sağlamanız yeterlidir:
public class Foo
{
public string Bar { get; }
public Foo(string bar)
{
Bar = bar;
}
}
Şimdi bu çalışıyor:
string json = "{ \"bar\": \"Stack Overflow\" }";
var deserialized = JsonConvert.DeserializeObject<Foo>(json);
Console.WriteLine(deserialized.Bar); // Stack Overflow
Bu yaklaşımı mümkün olduğunca tercih ediyorum çünkü:
{ get; private set; }ve hem de sadece çalışır { get; }.{get;private set;}değil ile,{get;}
{ get; }türün özellik adıyla eşleşen bir parametreye sahip bir kurucuya sahip olması durumunda işe yarıyor .
Bunun için iki özel sözleşme çözümleyicisiyle tek bir dosya yükleyen bir kaynak dağıtımı NuGet yazdım:
NuGet'i yükleyin:
Install-Package JsonNet.PrivateSettersContractResolvers.Source
Ardından çözücülerden herhangi birini kullanın:
var settings = new JsonSerializerSettings
{
ContractResolver = new PrivateSetterContractResolver()
};
var model = JsonConvert.DeserializeObject<Model>(json, settings);
Buradan okuyabilirsiniz: http://danielwertheim.se/json-net-private-setters-nuget/
GitHub deposu: https://github.com/danielwertheim/jsonnet-privatesetterscontractresolvers
Sorunu çözebilecek iki alternatif var.
Alt 1: Seriyi kaldırıcılarda
ContractResolver.DefaultMembersSearchFlags =
DefaultMembersSearchFlags | BindingFlags.NonPublic;
Varsayılan serileştirme seçeneği tüm sınıf üyelerini destekler. Bu nedenle bu çözüm, alanlar dahil tüm özel üye türlerini döndürecektir. Ben sadece özel pasörleri desteklemekle ilgileniyorum.
Alt2: Özel bir ContractResolver oluşturun:
Bu nedenle, özellikleri kontrol ettiğimiz için bu daha iyi seçeneklerdir.
public class SisoJsonDefaultContractResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(
MemberInfo member,
MemberSerialization memberSerialization)
{
//TODO: Maybe cache
var prop = base.CreateProperty(member, memberSerialization);
if (!prop.Writable)
{
var property = member as PropertyInfo;
if (property != null)
{
var hasPrivateSetter = property.GetSetMethod(true) != null;
prop.Writable = hasPrivateSetter;
}
}
return prop;
}
}
Daha fazla bilgi için gönderimi okuyun: http://danielwertheim.se/json-net-private-setters/
DefaultMembersSearchFlagsolmuştur kullanımdan kaldırıldı .
{get; }eşdeğer DEĞİLDİR { get; private set; }. İlk yol için property.GetSetMethod(true)geri döner nullve ikincisi true. Bu beni şaşırttı. private set;Serileştirmenin beklendiği gibi çalışması için sahip olmanız gerekir .
@ Daniel'in cevabı (Alt2) yerinde, ancak bunun hem özel ayarlayıcılar hem de alıcılar için çalışmasına ihtiyacım vardı (Aslında, sadece yazılabilen birkaç şeye sahip bir API ile çalışıyorum user.password.) İşte bulduğum şey:
public class NonPublicPropertiesResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) {
var prop = base.CreateProperty(member, memberSerialization);
if (member is PropertyInfo pi) {
prop.Readable = (pi.GetMethod != null);
prop.Writable = (pi.SetMethod != null);
}
return prop;
}
}
Bu şekilde kaydedildi:
JsonConvert.DefaultSettings = () => new JsonSerializerSettings {
ContractResolver = new NonPublicPropertiesResolver()
};