Я знаю, что есть атрибут для обработки частных установщиков, но я хочу, чтобы это поведение использовалось по умолчанию, есть ли способ сделать это? За исключением настройки источника. Было бы здорово, если бы для этого была настройка.
95
Ответы:
Я пришел сюда в поисках фактического атрибута, который заставляет 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; }
.источник
{get;private set;}
{get;}
{ get; }
если у типа есть конструктор с параметром, соответствующим имени свойства.Обновленный, новый ответ
Я написал для этого исходный дистрибутив NuGet, который устанавливает один файл с двумя настраиваемыми преобразователями контрактов:
Установите NuGet:
Затем просто используйте любой из резолверов:
var settings = new JsonSerializerSettings { ContractResolver = new PrivateSetterContractResolver() }; var model = JsonConvert.DeserializeObject<Model>(json, settings);
Вы можете прочитать об этом здесь: http://danielwertheim.se/json-net-private-setters-nuget/
Репозиторий GitHub: https://github.com/danielwertheim/jsonnet-privatesetterscontractresolvers
Старый ответ (еще действующий)
Есть две альтернативы, которые могут решить проблему.
Альтернативный вариант 1: о десериализаторах
Параметр сериализации по умолчанию поддерживает все типы членов класса. Поэтому это решение вернет все типы закрытых членов, включая поля. Меня интересует только поддержка частных сеттеров.
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/
источник
DefaultMembersSearchFlags
было устаревшим .{get; }
НЕ эквивалентен{ get; private set; }
. По первому способуproperty.GetSetMethod(true)
возвращаетсяnull
и второйtrue
. Это меня удивило. Вы должны иметь,private set;
чтобы десериализация работала должным образом .Ответ @ Daniel (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() };
источник