【问题标题】:how to display enum number instead of enum name in response如何在响应中显示枚举编号而不是枚举名称
【发布时间】:2022-10-03 03:16:29
【问题描述】:

尝试使用 hotchocolate 获得答案时,在枚举类型的字段中,答案是字符串的形式,我需要一个枚举值

[UseProjection]
    public IQueryable<Cart> GetActualCart([Service] ApplicationDbContext context, ClaimsPrincipal claimsPrincipal, int pageNumber = 1, int pageSize = 10)
    {
        var userId = claimsPrincipal.FindFirstValue(ClaimTypes.NameIdentifier);
        return context.Carts
            .Where(f => f.CourierId == new Guid(userId))
            .FromPage(pageNumber, pageSize);
    }

public class Cart : AuditableBaseEntity<Guid>
{
    public Guid CourierId { get; set; }
    public CartStatus Status { get; set; } = CartStatus.Building;
    public virtual ICollection<CartItem> Items { get; set; } = new HashSet<CartItem>();
}

public enum CartStatus
{
    Building = 1,
    WarehouseDelivery = 2,
    WarehouseRefund = 3, 
    CartRefund = 4, 
}

回复:

\"data\": {
\"actualCart\": [
  {
    \"courierId\": \"efb60c9e-c6fe-4479-bd93-82fb23ad63b5\",
    \"status\": \"BUILDING\"
  },
  {
    \"courierId\": \"efb60c9e-c6fe-4479-bd93-82fb23ad63b5\",
    \"status\": \"WAREHOUSE_DELIVERY\"
  }
]

  • 你为什么要这个?在生成的架构中,您已经指定 Status 是一个枚举,这些是它的值。客户已经明白这一点——客户应该尊重已发布的模式。
  • 除非您确保 GraphQL 架构说 Status不是一个枚举,所有有效的客户端都将被破坏

标签: c# .net enums graphql hotchocolate


【解决方案1】:

GraphQL 枚举将始终产生名称作为响应。事实上,GraphQL 枚举元素名称不能以数字开头。

https://spec.graphql.org/October2021/#sec-Enum-Value

名称规范在这里: https://spec.graphql.org/October2021/#Name

【讨论】:

    【解决方案2】:

    如果可以接受 Cart.status 字段的类型为 Int 而不是枚举类型,则可以将 CartStatus 绑定到 IntType 并使用转换器:

    public void ConfigureServices(IServiceCollection services)
    {
        services
            .AddGraphQLServer()
            .BindRuntimeType<CartStatus, IntType>()
            .AddTypeConverter<CartStatus, int>(source => (int) source);
    }
    

    【讨论】:

      【解决方案3】:

      首先,API 的使用者不应该关心数字枚举值。如果他们这样做了,这清楚地表明您的抽象正在泄漏,并且您的消费者依赖于您的 API 的实现细节。

      话虽如此,正如迈克尔已经提到的那样,没有一种符合规范的方法可以将数字文字作为枚举值返回。您可以解决此问题,但您的服务器将不再符合规范,这将为您带来一系列全新的问题。

      解决问题的最简单方法是将枚举换成 Int 标量:

      // Each occurence of the CartStatus should be represented as Int
      .BindRuntimeType<CartStatus, IntType>()
      // How to convert a CartStatus to the integer value (output)
      .AddTypeConverter<CartStatus, int>(source => (int)source)
      // How to convert an int to the CartStatus enum value (input)
      .AddTypeConverter<int, CartStatus>(source => (CartStatus)source);
      

      如果您真的需要数字值,但为了便于发现,您还想保留枚举,您可以创建一个返回枚举值和数字值的包装器类型。假设你的枚举被命名为Status,你可以创建一个如下的包装对象:

      builder.Services
           .AddGraphQLServer()
           .BindRuntimeType<Status, StatusObjectType>();
       
       public class StatusObjectType : ObjectType
       {
           protected override void Configure(IObjectTypeDescriptor descriptor)
           {
               descriptor.Name("StatusObject");
       
               descriptor.Field("value")
                   .Type<EnumType<Status>>()
                   .Resolve(context => context.Parent<Status>());
       
               descriptor.Field("code")
                   .Resolve(context => (int)context.Parent<Status>());
           }
       }
      

      对于每个返回 Status 枚举的解析器,它将自动映射到此包装器对象。

      然后,消费者将能够像这样查询您的枚举字段:

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-11-01
        • 2019-06-20
        • 1970-01-01
        • 2018-05-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多