【问题标题】:API not returning JSON data in desired formatAPI 未以所需格式返回 JSON 数据
【发布时间】:2021-03-18 23:17:13
【问题描述】:

我正在将 .Net Core Entity Framework 3.1 用于汽车零件的 Web 目录应用程序。

我有一个简单的控制器,它返回特定电机的所有 motorParts

这是一个简单的控制器:

[HttpGet("GetPartsByMotorId/{id}")]
public async Task<ActionResult<IEnumerable<MotorParts>>> GetPartsByMotorId(Guid id)
{

   var partsByMotor = await _context.MotorParts.Where(q => q.MotorId == id).OrderBy(c => c.partText).ToListAsync();

    return partsByMotor;
}

它正在返回数据,但它的顺序是我不想要的,并且有一些数据重复。

从 API 返回时 JSON 如下所示:

[
    {
        "partId": "54",
        "motorId": "3",
        "partText": "Iron Heads",
        "motor": {
            "motorId": "3",
            "motorText": "5.7 HEMI",
            "motorParts": [
                {
                    "partId": "54",
                    "motorId": "3",
                    "partText": "Iron Heads"
                },
                {
                    "partId": "8",
                    "motorId": "3",
                    "partText": "Aluminum Block"
                }
            ]
        }
    },
    {
        "partId": "8",
        "motorId": "3",
        "partText": "Aluminum Block",
        "motor": {
            "motorId": "3",
            "motorText": "5.7 HEMI",
            "motorParts": [
                {
                    "partId": "8",
                    "motorId": "3",
                    "partText": "Aluminum Block"
                },
                {
                    "partId": "54",
                    "motorId": "3",
                    "partText": "Iron Heads"
                }
            ]
        }
    }
]

对我来说,问题是它首先列出一个“部分”(partId, motorId, partText),然后再列出相同的“部分”。

但我希望它首先列出电机数据,然后是该电机的所有部件,如下所示:

[
    {
        "motor": {
            "motorId": "3",
            "motorText": "5.7 HEMI",
            "motorParts": [
                {
                    "partId": "8",
                    "motorId": "3",
                    "partText": "Aluminum Block"
                },
                {
                    "partId": "54",
                    "motorId": "3",
                    "partText": "Iron Heads"
                }
            ]
        }
    }
]

这是模型:

public partial class MotorParts
{
    public Guid PartId { get; set; }
    public Guid? MotorId { get; set; }
    public string PartText { get; set; }

    public virtual MotorList Motor { get; set; }
}

这是该模型的数据库上下文:

modelBuilder.Entity<MotorParts>(entity =>
{
    entity.HasKey(e => e.PartId);

    entity.HasOne(d => d.Motor)
        .WithMany(p => p.MotorParts)
        .HasForeignKey(d => d.MotorId)
        .OnDelete(DeleteBehavior.Cascade)
        .HasConstraintName("FK_carList_makeList");

    entity.ToTable("MotorParts");

    entity.Property(e => e.PartId)
        .HasColumnName("PartId");

    entity.Property(e => e.MotorId)
        .HasColumnName("MotorId");

    entity.Property(e => e.PartText)
        .HasColumnName("PartText");
});

所以我想知道是否有一种方法可以在不过多更改模型的情况下获得我想要的 JSON 格式。这可能吗?

谢谢!

【问题讨论】:

    标签: c# asp.net-core entity-framework-core asp.net-core-webapi asp.net-core-3.1


    【解决方案1】:

    您应该提供正确的转换。此查询还需要客户端分组。

    var dataQuery = 
       from mi in _context.MotorParts
       where mp.MotorId == id
       select new 
       {
          Motor = new 
          { 
              motorId = mp.MotorId.Value,
              motorText = mp.Motor.MotorText 
          },
          MotorPart = new 
          { 
              partId = mp.PartId,
              motorId = mp.MotorId.Value,
              partText = mp.PartText
          }
       }
    
    var partsByMotor = 
       from mp in await dataQuery.ToListAsync()
       group mp.MotorPart by mp.Motor into g
       select new 
       {
           motorId = g.Key.motorId,
           motorText = g.Key.motorText,
           motorParts = g.OrderBy(x => x.partText).ToArray()
       };
    
    return partsByMotor.ToList();
       
    

    【讨论】:

      【解决方案2】:

      您是否研究过使用属性装饰属性以控制顺序的方法?
      与 NewtonSoft Json Property Order 非常相似。 https://www.newtonsoft.com/json/help/html/JsonPropertyOrder.htm

      【讨论】:

        【解决方案3】:

        您想要的返回看起来只是一个 Motor 对象返回,其中包括所有相关的 MotorPart 对象。您的模型设计存在一些问题,因为您有一个应该代表单个个体 MotorPartMotorParts 类,对吗?我不知道MotorParts 是否应该是对象本身的集合,或者多个MotorPart 对象是否在一个集合中。你上课的目的是什么?我认为它是为了代表个人MotorPart?如果是这样,它真的应该被命名为MotorPart

        事实上,EF 将每个 MotorParts 对象视为一个单独的电机部件,并将每个对象存储在 MotorParts 表中。这只是您的命名错误吗?运行查询时,您会得到一个 List&lt;MotorParts&gt; 返回集合。列表中的每个元素都包含对相关Motor 对象的引用,该对象还具有对电机部件的引用。根据您所说的预期结果,这似乎是一个相当糟糕的设计选择。

        最简单的建议是从 MotorParts 类中删除 Motor 属性并保留 MotorId 属性。这将消除对电机部件的冗余参考。尽管如此,这个查询还是返回了一个对象的集合。它不会返回包含相关 MotorParts 的单个 Motor 对象。

        如果您想返回单个 Motor 对象及其所有 MotorParts,那么您需要对 Motors 表运行查询。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-06-11
          • 2017-02-24
          • 1970-01-01
          • 1970-01-01
          • 2015-07-22
          • 2021-12-20
          • 1970-01-01
          相关资源
          最近更新 更多