Json.Net'te özel ayarlayıcılar


95

Ö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.


1
Aradığım bu ya o cevap.
marbel82

Yanıtlar:


115

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

Alternatif çözüm

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ü:

  • Mülklerinizi niteliklerle dekore etmenizi gerektirmez.
  • Hem { get; private set; }ve hem de sadece çalışır { get; }.

19
Sadece küçük bir not: ile çalışır {get;private set;}değil ile,{get;}
tymtam

8
Sadece küçük bir güncelleme. Artık {get;} ile de çalışıyor;
Hav

1
@Hav O zamandan beri hangi versiyon? Sadece v11.0.2 test ettik ve öyle değil iş {get;}
tymtam

1
@tymtam Bence, yalnızca { get; }türün özellik adıyla eşleşen bir parametreye sahip bir kurucuya sahip olması durumunda işe yarıyor .
Saeb Amini

2
@tymtam, yanıtı bu alternatif ve bir örnekle güncelledi.
Saeb Amini

77

Güncellenmiş, yeni cevap

Bunun için iki özel sözleşme çözümleyicisiyle tek bir dosya yükleyen bir kaynak dağıtımı NuGet yazdım:

  • PrivateSetterContractResolver
  • PrivateSetterCamelCasePropertyNamesContractResolver

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

Eski cevap (hala geçerli)

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/



1
@Jafin url, öldü danielwertheim.wordpress.com/2010/11/06/... şimdi o vardır
Chris Marisic

1
Görünüşe göre Alt 2 kesinlikle bugünlerde gitmenin yolu. DefaultMembersSearchFlagsolmuştur kullanımdan kaldırıldı .
Todd Menier

4
C # 6 ile {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 .
2016

Görünüşe göre Install-Package JsonNet.ContractResolvers şimdi kullanılmalı. github.com/danielwertheim/jsonnet-contractresolvers
Bağlantısızlar

14

@ 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()
};
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.