Saya tahu ada atribut untuk menangani penyetel pribadi tetapi saya ingin perilaku ini sebagai default, apakah ada cara untuk melakukannya? Kecuali mengubah sumbernya. Akan lebih bagus jika ada pengaturan untuk ini.
Saya datang ke sini mencari atribut sebenarnya yang membuat Json.NET mengisi properti hanya baca saat deserialisasi, dan itu sederhana [JsonProperty], misalnya:
[JsonProperty]
public Guid? ClientId { get; privateset; }
Solusi alternatif
Cukup sediakan konstruktor yang memiliki parameter yang cocok dengan properti Anda:
publicclassFoo
{
publicstring Bar { get; }
publicFoo(string bar)
{
Bar = bar;
}
}
var settings = new JsonSerializerSettings
{
ContractResolver = new PrivateSetterContractResolver()
};
var model = JsonConvert.DeserializeObject<Model>(json, settings);
Opsi serialisasi default mendukung semua jenis anggota kelas. Oleh karena itu, solusi ini akan mengembalikan semua jenis anggota pribadi termasuk bidang. Saya hanya tertarik juga mendukung setter pribadi.
Alt2: Buat ContractResolver kustom:
Oleh karena itu, ini adalah opsi yang lebih baik karena kami baru saja memeriksa properti.
publicclassSisoJsonDefaultContractResolver : DefaultContractResolver
{
protectedoverride JsonProperty CreateProperty(
MemberInfo member,
MemberSerialization memberSerialization)
{
//TODO: Maybe cachevar 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;
}
}
Sepertinya Alt 2 jelas merupakan cara terbaik saat ini. DefaultMembersSearchFlagssudah tidak digunakan lagi .
Todd Menier
4
Dengan c # 6, {get; }TIDAK setara dengan { get; private set; }. Untuk cara pertama property.GetSetMethod(true)kembali nulldan yang terakhir true. Ini mengejutkan saya. Anda harus memiliki private set;deserialization untuk bekerja seperti yang diharapkan.
@ Jawaban Daniel (Alt2) tepat, tetapi saya membutuhkan ini untuk bekerja baik untuk penyetel pribadi dan pengambil (saya bekerja dengan API yang sebenarnya memiliki beberapa hal hanya-tulis, seperti user.password.) Inilah yang akhirnya saya dapatkan:
Jawaban:
Saya datang ke sini mencari atribut sebenarnya yang membuat Json.NET mengisi properti hanya baca saat deserialisasi, dan itu sederhana
[JsonProperty]
, misalnya:[JsonProperty] public Guid? ClientId { get; private set; }
Solusi alternatif
Cukup sediakan konstruktor yang memiliki parameter yang cocok dengan properti Anda:
public class Foo { public string Bar { get; } public Foo(string bar) { Bar = bar; } }
Sekarang ini berhasil:
string json = "{ \"bar\": \"Stack Overflow\" }"; var deserialized = JsonConvert.DeserializeObject<Foo>(json); Console.WriteLine(deserialized.Bar); // Stack Overflow
Saya lebih suka pendekatan ini jika memungkinkan karena:
{ get; private set; }
dan adil{ get; }
.sumber
{get;private set;}
, bukan dengan{get;}
{ get; }
jika tipe tersebut memiliki konstruktor dengan parameter yang cocok dengan nama properti.Diperbarui, jawaban baru
Saya telah menulis distribusi sumber NuGet untuk ini, yang menginstal satu file dengan dua resolver kontrak khusus:
Instal NuGet:
Kemudian gunakan salah satu resolver:
var settings = new JsonSerializerSettings { ContractResolver = new PrivateSetterContractResolver() }; var model = JsonConvert.DeserializeObject<Model>(json, settings);
Anda dapat membacanya di sini: http://danielwertheim.se/json-net-private-setters-nuget/
Repo GitHub: https://github.com/danielwertheim/jsonnet-privatesetterscontractresolvers
Jawaban lama (masih valid)
Ada dua alternatif yang bisa mengatasi masalah tersebut.
Alt 1: Di deserializers
Opsi serialisasi default mendukung semua jenis anggota kelas. Oleh karena itu, solusi ini akan mengembalikan semua jenis anggota pribadi termasuk bidang. Saya hanya tertarik juga mendukung setter pribadi.
Alt2: Buat ContractResolver kustom:
Oleh karena itu, ini adalah opsi yang lebih baik karena kami baru saja memeriksa properti.
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; } }
Untuk informasi lebih lanjut, baca posting saya: http://danielwertheim.se/json-net-private-setters/
sumber
DefaultMembersSearchFlags
sudah tidak digunakan lagi .{get; }
TIDAK setara dengan{ get; private set; }
. Untuk cara pertamaproperty.GetSetMethod(true)
kembalinull
dan yang terakhirtrue
. Ini mengejutkan saya. Anda harus memilikiprivate set;
deserialization untuk bekerja seperti yang diharapkan.@ Jawaban Daniel (Alt2) tepat, tetapi saya membutuhkan ini untuk bekerja baik untuk penyetel pribadi dan pengambil (saya bekerja dengan API yang sebenarnya memiliki beberapa hal hanya-tulis, seperti
user.password
.) Inilah yang akhirnya saya dapatkan: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; } }
Terdaftar sebagai berikut:
JsonConvert.DefaultSettings = () => new JsonSerializerSettings { ContractResolver = new NonPublicPropertiesResolver() };
sumber