我从Odoo API得到了以下响应,我想使用Newtonsoft.Json将其反序列化为C#POCO:

{
    "jsonrpc": "2.0",
    "id": 88252859,
    "result": [
        {
            "id": 61,
            "campaign_id": false,
            "source_id": false,
            "medium_id": false,
            "activity_ids": [],
            "activity_state": false,
            "activity_user_id": false,
            "activity_type_id": false,
            "activity_type_icon": false,
            "activity_date_deadline": false,
            "my_activity_date_deadline": false,
            "activity_summary": false,
            "activity_exception_decoration": false,
            "activity_exception_icon": false,
            "activity_calendar_event_id": false,
            (...)
        }
    ]
}

问题是,Odoo API在响应中用false替换了null.例如:属性my_activity_date_deadline的类型为DateTime?,但Odoo将其返回为false.这适用于任何可为空的类型.

我应该如何处理这件事?一个定制的JsonConverter级?或者,也许我应该捕获并静默类型不匹配导致的异常,以便在无法反序列化属性时使用缺省值?

我在GitHub上找到了一个潜在的解决方案,在OdooModelConverter中使用方法ConverOdooPropertyToDotNet:

这感觉有点老生常谈,但我不知道如何写出更优雅的解决方案.

推荐答案

使用这个简单的转换器:

public class FalseToNullConverter : JsonConverter
{
    public override bool CanConvert(Type objectType) => true;

    public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
        => reader.TokenType != JsonToken.Boolean || reader.Value is not false 
            ? serializer.Deserialize(reader, objectType)
            : null;

    public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
        => throw new NotImplementedException();
}

您可以在您的POCO类中修饰那些需要被视为可空字段的属性,例如

public class OdooResult
{
    public int id { get; set; }

    [JsonConverter(typeof(FalseToNullConverter))]
    public int? campaign_id { get; set; }

    [JsonConverter(typeof(FalseToNullConverter))]
    public Guid? source_id { get; set; }

    [JsonConverter(typeof(FalseToNullConverter))]
    public long? medium_id { get; set; }

    public List<object> activity_ids { get; set; }

    public bool activity_state { get; set; }

    [JsonConverter(typeof(FalseToNullConverter))]
    public int? activity_user_id { get; set; }

    [JsonConverter(typeof(FalseToNullConverter))]
    public int? activity_type_id { get; set; }

    public bool activity_type_icon { get; set; }

    [JsonConverter(typeof(FalseToNullConverter))]
    public DateTime? activity_date_deadline { get; set; }

    [JsonConverter(typeof(FalseToNullConverter))]
    public DateTime? my_activity_date_deadline { get; set; }

    public bool activity_summary { get; set; }

    public bool activity_exception_decoration { get; set; }

    public bool activity_exception_icon { get; set; }

    public bool activity_calendar_event_id { get; set; }
}

已知限制

如果您收到true,例如campaign_id,那么它将被反序列化为1.根据您的需求,这需要有不同的处理方式.

Csharp相关问答推荐

当前文化和当前文化之间没有区别IgnoreCase,为什么?

使用ElasticsearchClient设置忽略属性.默认MappingFor<>

有没有办法把+02:00转换成TimeSpan?""

如何在Reflection. Emit中使用具有运行时定义的类型参数的泛型类型

处理. netstandard2.0项目中HttpClient.SslProtocol的PlatformNotSupportedException问题""

. NET JSON属性自定义所需逻辑

在实时数据库中匹配两个玩家的问题

从应用程序图API调用访问所有者字段

Mongo作为.NET中Testcontainers的副本集

将现有字段映射到EFCore中的复杂类型

在具有不同属性名称的两个类之间创建关系

C#和ASP.NET核心标识:提高GetUserAsync调用的性能

从VS调试器而不是测试资源管理器运行的调试NUnitDotNet测试

HttpClient SendAsync与多线程环境中的ArchiveZip

链接到字典字符串.拆分为(.Key,.Value)

C#LINQ子字符串

多个选项卡上的MudForm验证

C#中类库项目的源代码生成器

C# Winforms:从对象树到TreeView的递归转换重复条目

在C#和HttpClient中使用REST API