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.
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; privateset; }
Alternatywne rozwiązanie
Po prostu podaj konstruktor, który ma parametr pasujący do Twojej właściwości:
publicclassFoo
{
publicstring Bar { get; }
publicFoo(string bar)
{
Bar = bar;
}
}
var settings = new JsonSerializerSettings
{
ContractResolver = new PrivateSetterContractResolver()
};
var model = JsonConvert.DeserializeObject<Model>(json, settings);
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.
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;
}
}
Wygląda na to, że Alt 2 jest obecnie zdecydowanie właściwą drogą. DefaultMembersSearchFlagszostał wycofany .
Todd Menier
4
C # 6 {get; }NIE jest równoważne z { get; private set; }. Po pierwsze sposób property.GetSetMethod(true)powraca, nulla 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ę:
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; }
Alternatywne rozwiązanie
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; }
.źródło
{get;private set;}
, a nie z{get;}
{ get; }
wtedy, gdy typ ma konstruktora z parametrem pasującym do nazwy właściwości.Zaktualizowana, nowa odpowiedź
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:
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
Stara odpowiedź (nadal ważna)
Istnieją dwie alternatywy, które mogą rozwiązać ten problem.
Alt 1: na deserializatorach
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/
źródło
DefaultMembersSearchFlags
został wycofany .{get; }
NIE jest równoważne z{ get; private set; }
. Po pierwsze sposóbproperty.GetSetMethod(true)
powraca,null
a drugitrue
. 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() };
źródło