POST JSON 对象以枚举 id 作为数字,响应返回枚举字符串名称而不是 int id

问题描述

只是想知道为什么当我发送带有数字 id 的 JSON 时:

{
    "name": "yummy food","tags": [
        {
            "name": "Indian","id": "9","iconCodePoint": 23145
        }
    ]
}

字段 Tags 以这样的数字 id 存储在数据库中:

enter image description here

但是字段 Tags 在响应中具有枚举 string name 作为 id 字段:

{
    "name": "yummy food","description": null,"image": null,"menuyItemRestaurants": null,"id": 7,"isNotVeganCount": 0,"isVeganCount": 0,"ratingsCount": 0,"rating": 0,"tags": [
        {
            "id": "Indian",<----------- HERE
            "iconCodePoint": 23145,"name": "Indian"
        }
    ],"establishments": null,"currentRevisionId": 0
}

添加更多字段的枚举的“类”版本:

using System.Text.Json.Serialization;
namespace Vepo.Domain
{
    public class MenuItemTag
    {
        [JsonConstructor]
        public MenuItemTag(string name,MenuItemTagEnum id,int iconCodePoint)
        {
            Id = id;
            IconCodePoint = iconCodePoint;
            Name = name;
        }

        public MenuItemTagEnum Id { get; set; }
        public int IconCodePoint { get; set; }
        public string Name { get; set; }
    }
}

枚举:

public enum MenuItemTagEnum
{
  Asian = 1,Barbecue,European,Bakery,Cafe,Deli,Desserts,FishAndChips,Indian,American,PubFood,Breakfast,Chinese,Fench,German,Japanese,Kebab,Mediterranian,LatinAmerican,MiddleEastern,Salad,Thai,Turkish,Vietnamese,Mexican,Sushi,Kiwi,Greek,HealthFood,Other,Korean,Italian
} 

MenuItem.Tags 字段序列化为一个 string 表列的数据库上下文:

protected override void OnModelCreating(ModelBuilder builder)
{
    builder.Entity<MenuItemTag>()
        .Property(tag => tag.Id)
        .HasConversion<int>()
        .ValueGeneratedNever();

    builder.Entity<MenuItemTag>().HasData(
        new MenuItemTag[] {
        new MenuItemTag(
            "American",MenuItemTagEnum.American,0xf803
        ),new MenuItemTag(
            "Asian",MenuItemTagEnum.Asian,0xf823
        ),new MenuItemTag(
            "Bakery",MenuItemTagEnum.Bakery,0xf705
        ),new MenuItemTag(
            "Barbecue",MenuItemTagEnum.Barbecue,0xf80f
        ),new MenuItemTag(
            "Breakfast",MenuItemTagEnum.Breakfast,0xe002
        ),new MenuItemTag(
            "Cafe",MenuItemTagEnum.Cafe,0xf6c5
        ),new MenuItemTag(
            "Chinese",MenuItemTagEnum.Chinese,new MenuItemTag(
            "Deli",MenuItemTagEnum.Deli,0xf81f
        ),new MenuItemTag(
            "Desserts",MenuItemTagEnum.Desserts,0xf551
        ),new MenuItemTag(
            "European",MenuItemTagEnum.European,0xf7a2
        ),new MenuItemTag(
            "Fish & Chips",MenuItemTagEnum.FishAndChips,0xf7fe
        ),new MenuItemTag(
            "Indian",MenuItemTagEnum.Indian,0xf156
        ),new MenuItemTag(
            "French",MenuItemTagEnum.Fench,0xf7f6
        ),new MenuItemTag(
            "German",MenuItemTagEnum.German,0xf820
        ),new MenuItemTag(
            "Greek",MenuItemTagEnum.Greek,0xf68b
        ),new MenuItemTag(
            "Health Food",MenuItemTagEnum.HealthFood,0xf81e
        ),new MenuItemTag(
            "Italian",MenuItemTagEnum.Italian,0xf817
        ),new MenuItemTag(
            "Japanese",MenuItemTagEnum.Japanese,0xf56a
        ),new MenuItemTag(
            "Kebab",MenuItemTagEnum.Kebab,0xf821
        ),new MenuItemTag(
            "Kiwi",MenuItemTagEnum.Kiwi,0xf535
        ),new MenuItemTag(
            "Korean",MenuItemTagEnum.Korean,0xf159
    )});

    builder.Entity<MenuItem>()
    .Property(e => e.Tags)
    .HasConversion(
        v => JsonSerializer.Serialize(v,null),v => JsonSerializer.Deserialize<List<MenuItemTag>>(v,new ValueComparer<IList<MenuItemTag>>(
            (c1,c2) => c1.SequenceEqual(c2),c => c.Aggregate(0,(a,v) => HashCode.Combine(a,v.GetHashCode())),c => (IList<MenuItemTag>)c.ToList()));

控制器:

// POST: api/MenuItems
// To protect from overposting attacks,see https://go.microsoft.com/fwlink/?linkid=2123754
[HttpPost]
public async Task<ActionResult<MenuItem>> PostMenuItem(MenuItem menuItem)
{
    _context.MenuItems.Add(menuItem);
    await _context.SaveChangesAsync();

    return CreatedAtAction("GetMenuItem",new { id = menuItem.Id },menuItem);
}

知道如何将 MenuItem.Tags 的数据库转换器转换回 int id 以发送 JSON 响应而不是字符串枚举名称吗?

我认为这段代码可以做到:

builder.Entity<MenuItemTag>()
    .Property(tag => tag.Id)
    .HasConversion<int>()
    .ValueGeneratedNever();

解决方法

您可以轻松设置自己的转换

.HasConversion() => {
    set => Enum.GetName(typeof(<YourEnum>),set),get => {
      <your switch case>
    }
}

我已经在我当前的项目中使用 List 做到了这一点。
我写了一个“获取转换函数”的小PoC:
Conversion Example
Implementation Example/PoC Switch

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...