多个DataMemberAttribute

时间:2018-03-18 06:59:38

标签: f# datacontract

主题

对于错误,api返回两种结果,一种是字段error,一种是error_code,api可以根据参数返回两种类型,因此可以&#t; t真的在那里分支。

Deserialize datamember multiple names (C#)

JSON 1

{
    "error_code": "234",
    "message": "Api Key is required"
}

JSON 2

{
    "code": "NotFound",
    "message": "Could not find the resource"
}

代码

[<DataContract>]
type Error = {
    [<field: DataMemberAttribute(Name="code",Name="error_code")>]
    code: string
    [<field: DataMemberAttribute(Name="message")>]
    message: string
}

错误

  

已为命名参数分配了多个值

预期解决方案

如果相同的错误类型可以处理两种类型的JSON输出。

根据给定的答案

修改

[<DataContract>]
type Error = {
    [<field: DataMemberAttribute(Name="code")>]
    code: string

    [<field: DataMemberAttribute(Name="error_code")>]
    error_code: string

    [<field: DataMemberAttribute(Name="message")>]
    Message: string
} 
with member this.Code : string =
        if not (String.IsNullOrEmpty(this.code)) then this.code
        else if not (String.IsNullOrEmpty(this.error_code)) then this.error_code
        else ""

1 个答案:

答案 0 :(得分:2)

我不认为这对F#记录类型是直接可能的,但是根据反序列化器的行为,你可能会这样:

[<DataContract>]
type Error = {
    [<field: DataMemberAttribute(Name="error_code")>]
    numericCode: string
    [<field: DataMemberAttribute(Name="code")>]
    textCode: string
    [<field: DataMemberAttribute(Name="message")>]
    message: string
}
    with member this.code =
        if not (String.IsNullOrEmpty(this.numericCode)) then Some this.numericCode
        else if not (String.IsNullOrEmpty(this.textCode)) then Some this.textCode
        else None

这样您仍然需要明确处理类型中的不同情况,但它允许您只需从代码中调用error.code,而不必担心两个单独的字段。

根据您使用的反序列化库,您可以使用访问修饰符来隐藏两个字段(但这可能对记录不切实际)或使其类型为Option<string>,以便消费者知道类型他们应该处理缺失值。

如果您指定具有不同字段的多个示例,这也是FSharp.Data的JsonProvider所做的事情:它将它们合并在一起以创建能够表示所有示例的单个类型,并且所有示例中都没有值的可选字段例子。然后由您来编写辅助函数或为特定于应用程序的映射键入扩展。