多个数据成员属性

Multiple DataMemberAttribute

主题

对于错误,api 是 returning 两种结果,一种具有字段 error,对于某些 error_code,以及 api 可以 return 两种基于参数的类型,所以不能真正分支到那里。

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
}

错误

A named argument has been assigned more than one value

预期解决方案

如果相同的错误类型可以处理两种类型的 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 ""

我认为 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 所做的:它将它们合并在一起以创建一个能够表示所有示例的单一类型,带有可选字段对于所有示例中不存在的值。然后由您为特定于应用程序的映射编写辅助函数或类型扩展。