Json.Net의 개인 세터


94

개인 setter를 처리하는 속성이 있다는 것을 알고 있지만이 동작을 기본값으로 원합니다.이를 수행하는 방법이 있습니까? 소스 조정을 제외하고. 이것에 대한 설정이 있다면 좋을 것입니다.


1
나는 이것 또는 대답을 찾고 있었다 .
marbel82

답변:


113

역 직렬화 할 때 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; }.

19
그냥 작은 노트 : 그것은 작동 {get;private set;}하지로,{get;}
tymtam

8
약간의 업데이트입니다. 이제 {get;}에서도 작동합니다.
Hav

1
@Hav 이후 버전은 무엇입니까? 방금 v11.0.2를 테스트했는데 작동 하지 않습니다 {get;}
tymtam

1
@tymtam { get; }유형에 속성 이름과 일치하는 매개 변수가있는 생성자가있는 경우 에만 작동한다고 생각합니다 .
Saeb Amini

2
@tymtam 은이 대안과 예제로 답변을 업데이트했습니다.
Saeb Amini

77

업데이트 된 새로운 답변

두 개의 사용자 지정 계약 해결 프로그램이있는 단일 파일을 설치하는 소스 배포 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 저장소 : 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/




1
Alt 2 는 확실히 요즘 갈 길인 것 같습니다 . DefaultMembersSearchFlags되었습니다 되지 .
Todd Menier 2015-06-29

4
C # 6, {get; }같지 않습니다 { get; private set; }. 첫 번째 방법 property.GetSetMethod(true)은 반환 null하고 후자 는 반환합니다 true. 이것은 나를 놀라게했다. private set;deserialization이 예상대로 작동 하려면 있어야합니다 .
emragins

이제 Install-Package JsonNet.ContractResolvers를 사용해야하는 것 같습니다. github.com/danielwertheim/jsonnet-contractresolvers
정렬

14

@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()
};
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.