Json.Net을 사용하여 Null 대신 F # 레코드의 빈 목록으로 누락 된 속성을 역 직렬화하는 방법

션 키론

다음과 같은 목록 값이 포함 된 F # 레코드를 고려하십시오.

type MyRecord = {
    Name: string
    SomeList: string list
}

사용 Netwonsoft.Json.JsonConvertjson으로 목록 값 속성이 포함되어 있지 않을 경우이 레코드에 JSON을 deserialise하는 Values갖는 직렬화 복원 기록으로 이어질 것입니다 레코드를 null목록 대신 빈리스트의 가치를 [].

그건,

open Newtonsoft.Json
JsonConvert.DeserializeObject<MyRecord>("""{ "Name": "Some name"}""" ) |> printfn "%A"
// Gives: { Name = "Some name"; SomeList = null; }

Netwonsoft.Json목록이 빈 목록으로 초기화되도록 어떻게 deserialise 할 수 있습니까? 예를 들면 :

{ Name = "Some name"; SomeList = []; }
dbc

다음과 같은 사용자 지정 계약 해결 프로그램을 사용하여이를 수행 할 수 있습니다 .

type ParameterizedConstructorInitializingContractResolver() =
    inherit DefaultContractResolver()

    // List is a module not a static class so it's a little inconvenient to access via reflection.  Use this wrapper instead.
    static member EmptyList<'T>() = List.empty<'T>

    override __.CreatePropertyFromConstructorParameter(matchingMemberProperty : JsonProperty, parameterInfo : ParameterInfo) =
        let property = base.CreatePropertyFromConstructorParameter(matchingMemberProperty, parameterInfo)
        if (not (matchingMemberProperty = null) && property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition() = typedefof<_ list>) then
            let genericMethod = typeof<ParameterizedConstructorInitializingContractResolver>.GetMethod("EmptyList", BindingFlags.Public ||| BindingFlags.NonPublic ||| BindingFlags.Static)
            let concreteMethod = genericMethod.MakeGenericMethod(property.PropertyType.GetGenericArguments())
            let defaultValue = concreteMethod.Invoke(null, null)
            property.DefaultValue <- defaultValue
            property.DefaultValueHandling <- new System.Nullable<DefaultValueHandling>(DefaultValueHandling.Populate)
            matchingMemberProperty.DefaultValue <- defaultValue
            matchingMemberProperty.DefaultValueHandling <- new System.Nullable<DefaultValueHandling>(DefaultValueHandling.Populate)
        property

그리고 다음과 같이 사용하십시오.

let settings = JsonSerializerSettings(ContractResolver = new ParameterizedConstructorInitializingContractResolver())

let myrecord1 = JsonConvert.DeserializeObject<MyRecord>("""{ "Name": "Missing SomeList"}""", settings )
let myrecord2 = JsonConvert.DeserializeObject<MyRecord>("""{ "Name": "Populated SomeList", "SomeList" : ["a", "b", "c"]}""", settings )
let myrecord3 = JsonConvert.DeserializeObject<MyRecord>("""{ "Name": "null SomeList", "SomeList" : null}""", settings )

메모:

  • 계약 확인자는 f # 레코드를 포함하지만 이에 국한되지 않는 매개 변수화 된 생성자를 통해 역 직렬화되는 모든 개체에 대해 작동 합니다. 그러한 객체 T list에 any에 대한 유형이있는 생성자 인수가있는 T경우 값은 List.empty<T>누락 된 경우 또는 null로 기본 설정됩니다 .

  • 계약 확인자는 List.empty<T>모든 역 직렬화 된 개체에 대해 동일한 기본값 인스턴스를 재사용 합니다. 이는 f # 목록이 변경 불가능하고 List.empty<T>어쨌든 싱글 톤 인 것 같기 때문에 여기에서는 괜찮습니다 . 동일한 접근 방식은 변경 가능한 컬렉션에 대한 기본값을 생성자 인수로 제공하는 데 작동하지 않습니다.

  • 최상의 성능을 위해 계약 해결 프로그램캐시 할 수 있습니다 .

  • 생성자 매개 변수는 해당 속성과 동일한 이름 (모듈로 대소 문자)을 가져야합니다.

여기에 데모 바이올린 .

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

Related 관련 기사

뜨겁다태그

보관