Частные сеттеры в Json.Net
Я знаю, что есть атрибут для обработки частных сеттеров, но я хочу, чтобы это поведение было по умолчанию, есть ли способ сделать это? Кроме настройки источника. Было бы здорово, если бы была установка для этого.
3 ответа:
Я пришел сюда в поисках фактического атрибута, который делает Json.NET заполните свойство readonly при десериализации, и это просто
[JsonProperty]
, например:[JsonProperty] public Guid? ClientId { get; private set; }
Альтернативный Вариант
просто укажите конструктор, который имеет параметр, соответствующий вашему свойству:
public class Foo { public string Bar { get; } public Foo(string bar) { Bar = bar; } }
теперь это работает:
string json = "{ \"bar\": \"Stack Overflow\" }"; var deserialized = JsonConvert.DeserializeObject<Foo>(json); Console.WriteLine(deserialized.Bar); // Stack Overflow
Я предпочитаю этот подход, где это возможно, так как:
- это не требует от вас, чтобы украсить свои свойства с атрибуты.
- он работает с
{ get; private set; }
и просто{ get; }
.
обновленный, новый ответ
Я написал исходный дистрибутив NuGet для этого, который устанавливает один файл с двумя пользовательскими преобразователями контрактов:
- PrivateSetterContractResolver
- PrivateSetterCamelCasePropertyNamescontractresolver
установите NuGet:
Install-Package JsonNet.PrivateSettersContractResolvers.Source
тогда просто используйте любой из решателей:
var settings = new JsonSerializerSettings { ContractResolver = new PrivateSetterContractResolver() }; var model = JsonConvert.DeserializeObject<Model>(json, settings);
вы можете прочитать об этом здесь: http://danielwertheim.se/json-net-private-setters-nuget/
GitHub repo:https://github.com/danielwertheim/jsonnet-privatesetterscontractresolvers
старый ответ (все еще действителен)
есть две альтернативы, которые могут решить эту проблему.
АЛТ 1: на десериализаторы
ContractResolver.DefaultMembersSearchFlags = DefaultMembersSearchFlags | BindingFlags.NonPublic;
возможность сериализации по умолчанию поддерживает все типы членов класса. Поэтому это решение вернет все типы частных членов, включая поля. Я заинтересован только в поддержке частных сеттеров.
Alt2: создать пользовательский ContractResolver:
поэтому это лучшие варианты, так как мы просто проверяем свойства.
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; } }
для получения дополнительной информации, прочитайте мой пост:http://danielwertheim.se/json-net-private-setters/
@Daniel's answer (Alt2) находится на месте, но мне нужно было это работать как для частных сеттеров, так и для геттеров (я работаю с API, который на самом деле имеет несколько вещей только для записи, например
user.password
.) Вот что у меня получилось: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; } }
зарегистрирован таким образом:
JsonConvert.DefaultSettings = () => new JsonSerializerSettings { ContractResolver = new NonPublicPropertiesResolver() };