Wiem, że istnieje atrybut do obsługi ustawień prywatnych, ale chcę, aby to zachowanie było domyślne, czy istnieje sposób, aby to osiągnąć? Z wyjątkiem poprawiania źródła. Byłoby wspaniale, gdyby było do tego miejsce.
Odpowiedzi:
Przyszedłem tutaj, szukając rzeczywistego atrybutu, który sprawia, że Json.NET wypełnia właściwość tylko do odczytu podczas deserializacji, a to po prostu [JsonProperty]
, np:
[JsonProperty]
public Guid? ClientId { get; private set; }
Po prostu podaj konstruktor, który ma parametr pasujący do Twojej właściwości:
public class Foo
{
public string Bar { get; }
public Foo(string bar)
{
Bar = bar;
}
}
Teraz to działa:
string json = "{ \"bar\": \"Stack Overflow\" }";
var deserialized = JsonConvert.DeserializeObject<Foo>(json);
Console.WriteLine(deserialized.Bar); // Stack Overflow
Preferuję takie podejście, jeśli to możliwe, ponieważ:
{ get; private set; }
i tylko { get; }
.{get;private set;}
, a nie z{get;}
{ get; }
wtedy, gdy typ ma konstruktora z parametrem pasującym do nazwy właściwości.
Napisałem w tym celu NuGet dystrybucji źródłowej, który instaluje pojedynczy plik z dwoma niestandardowymi programami do rozpoznawania umów:
Zainstaluj NuGet:
Install-Package JsonNet.PrivateSettersContractResolvers.Source
Następnie użyj dowolnego z resolwerów:
var settings = new JsonSerializerSettings
{
ContractResolver = new PrivateSetterContractResolver()
};
var model = JsonConvert.DeserializeObject<Model>(json, settings);
Możesz o tym przeczytać tutaj: http://danielwertheim.se/json-net-private-setters-nuget/
Repozytorium GitHub: https://github.com/danielwertheim/jsonnet-privatesetterscontractresolvers
Istnieją dwie alternatywy, które mogą rozwiązać ten problem.
Alt 1: na deserializatorach
ContractResolver.DefaultMembersSearchFlags =
DefaultMembersSearchFlags | BindingFlags.NonPublic;
Domyślna opcja serializacji obsługuje wszystkie typy elementów członkowskich klasy. Dlatego to rozwiązanie zwróci wszystkie prywatne typy członków, w tym pola. Interesuje mnie tylko wspieranie seterów prywatnych.
Alt2: Utwórz niestandardowy ContractResolver:
Dlatego jest to lepsza opcja, ponieważ po prostu sprawdzamy właściwości.
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;
}
}
Aby uzyskać więcej informacji, przeczytaj mój post: http://danielwertheim.se/json-net-private-setters/
DefaultMembersSearchFlags
został wycofany .
{get; }
NIE jest równoważne z { get; private set; }
. Po pierwsze sposób property.GetSetMethod(true)
powraca, null
a drugi true
. To mnie zaskoczyło. Musisz mieć, private set;
aby deserializacja działała zgodnie z oczekiwaniami.
Odpowiedź @ Daniela (Alt2) jest na miejscu, ale potrzebowałem tego do pracy zarówno dla prywatnych ustawiaczy, jak i pobierających (pracuję z API, które faktycznie ma kilka rzeczy tylko do zapisu, np user.password
.) Oto, co skończyło się:
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;
}
}
Zarejestrowany w ten sposób:
JsonConvert.DefaultSettings = () => new JsonSerializerSettings {
ContractResolver = new NonPublicPropertiesResolver()
};