You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET WebAPI中JSON数组转C#对象的EF Core序列化与迁移问题求助

问题

我正在构建一个通过POST操作接收JSON的.NET WebAPI,接收的JSON格式如下:

{
  "site": "00131231201d010231",
  "publishTime": 123123123123,
  "domains": [
    "example.com"
  ],
  "publishedBy": {
    "name": "John Doe",
    "id": "00211231201d010231"
  }
}

我将JSON映射为如下C#对象:

public class Project
{
    [Key]
    [JsonPropertyName("site")]
    public string Site { get; set; }

    [JsonPropertyName("publishTime")]
    public long PublishTime { get; set; }

    [JsonPropertyName("domains")]
    public List<Domain> Domains { get; set; }

    [JsonPropertyName("publishedBy")]
    public PublishedBy PublishedBy { get; set; }
}

public class PublishedBy
{
    [JsonPropertyName("name")]
    public string Name { get; set; }

    [Key]
    [JsonPropertyName("id")]
    public string Id { get; set; }
}

public class Domain
{
    [Key]
    public string Id { get; set; }
    public string Name { get; set; }
}

我的目标是将内容存入数据库,但使用List<string>作为Domains类型时,EF Core迁移报错,提示无法使用字符串类型。于是我创建了Domain类,但此时反序列化时出现错误:

System.Text.Json.JsonException: The JSON value could not be converted to spine_management.Models.Domain.

请问Domains应设置为何种类型,以及最佳的反序列化方式是什么?注:我希望保留domains属性,不希望忽略或删除它。

解决方案

针对你的问题,有两种可行的处理方式,既能满足EF Core的数据库存储要求,又能正确完成JSON反序列化:

方式一:自定义JSON转换器

保留List<Domain>类型,通过自定义JsonConverter实现字符串到Domain对象的自动转换:

  1. 创建自定义转换器:
public class DomainConverter : JsonConverter<Domain>
{
    public override Domain Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        // 将JSON字符串映射为Domain的Name和Id(可根据需求调整Id生成逻辑)
        var domainName = reader.GetString();
        return new Domain { Id = domainName, Name = domainName };
    }

    public override void Write(Utf8JsonWriter writer, Domain value, JsonSerializerOptions options)
    {
        // 序列化时输出Name字段的字符串值
        writer.WriteStringValue(value.Name);
    }
}
  1. 在Project类的Domains属性上添加转换器标记:
[JsonPropertyName("domains")]
[JsonConverter(typeof(DomainConverter))]
public List<Domain> Domains { get; set; }

这样反序列化时,JSON中的字符串数组会自动转为List<Domain>,同时EF Core可以正常识别Domain实体进行迁移和存储。

方式二:拆分属性(兼顾序列化和EF存储)

在Project类中同时定义两个属性:一个用于JSON反序列化的List<string>,另一个用于EF存储的List<Domain>,通过属性逻辑自动同步:

public class Project
{
    [Key]
    [JsonPropertyName("site")]
    public string Site { get; set; }

    [JsonPropertyName("publishTime")]
    public long PublishTime { get; set; }

    // 仅用于JSON反序列化,不映射到数据库
    [JsonPropertyName("domains")]
    public List<string> DomainNames { get; set; }

    // 用于EF Core存储,忽略JSON序列化
    [JsonIgnore]
    public List<Domain> Domains { get; set; }

    [JsonPropertyName("publishedBy")]
    public PublishedBy PublishedBy { get; set; }

    // 反序列化完成后自动同步数据
    [OnDeserialized]
    private void OnDeserialized(StreamingContext context)
    {
        if (DomainNames != null)
        {
            Domains = DomainNames.Select(name => new Domain { Id = name, Name = name }).ToList();
        }
    }
}

这种方式通过分离序列化和存储的属性,避免了转换器的复杂逻辑,同时保证两端需求都能满足。

补充说明

  • 关于Domain类的Id字段:如果不想用域名作为Id,可以自行生成唯一标识(比如Guid),只需要在转换器或同步逻辑中调整Id的赋值即可。
  • EF Core迁移时,确保Domain类的配置正确(比如通过Fluent API设置主键关系),避免实体映射错误。

内容的提问来源于stack exchange,提问作者Dechaun Bakker

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 06:35:26