개인 setter를 처리하는 속성이 있다는 것을 알고 있지만이 동작을 기본값으로 원합니다.이를 수행하는 방법이 있습니까? 소스 조정을 제외하고. 이것에 대한 설정이 있다면 좋을 것입니다.
답변:
역 직렬화 할 때 Json.NET이 읽기 전용 속성을 채우도록하는 실제 속성을 찾고 있습니다 [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을 설치합니다.
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 저장소 : https://github.com/danielwertheim/jsonnet-privatesetterscontractresolvers
문제를 해결할 수있는 두 가지 대안이 있습니다.
Alt 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/
DefaultMembersSearchFlags되었습니다 되지 .
{get; }같지 않습니다 { get; private set; }. 첫 번째 방법 property.GetSetMethod(true)은 반환 null하고 후자 는 반환합니다 true. 이것은 나를 놀라게했다. private set;deserialization이 예상대로 작동 하려면 있어야합니다 .
@Daniel의 대답 (Alt2)이 자리 잡고 있지만 개인 setter와 getter 모두에서 작동하려면 이것이 필요했습니다 (실제로 user.password. 과 같은 몇 가지 쓰기 전용 기능이있는 API로 작업 중입니다 .) 다음은 최종 결과입니다.
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()
};