C# 返回嵌套JSON值的Web API

C# 返回嵌套JSON值的Web API,c#,sql,json,asp.net-web-api,C#,Sql,Json,Asp.net Web Api,我正在处理一个由web api返回的JSON结构,但有一个问题 比如说,我有两张桌子,团队和玩家。他们由TeamID(团队PK和玩家FK)加入 我希望我的API调用返回一些JSON格式,如下所示: [ { TeamId: 1, TeamName: 'Chicago Bulls', TeamPlayers: [ {PlayerId: 1, PlayerName: 'Pau Gasol'}, {P

我正在处理一个由web api返回的JSON结构,但有一个问题

比如说,我有两张桌子,
团队
玩家
。他们由
TeamID
(团队PK和玩家FK)加入

我希望我的API调用返回一些JSON格式,如下所示:

[
    {
        TeamId: 1,
        TeamName: 'Chicago Bulls',
        TeamPlayers: [
            {PlayerId: 1, PlayerName: 'Pau Gasol'},
            {PlayerId: 2, PlayerName: 'Derrick Rose'},
            {PlayerId: 3, PlayerName: 'Joakim Noah'},
            {PlayerId: 4, PlayerName: 'Jimmy Butler'},
            {PlayerId: 5, PlayerName: 'Taj Gibson'}]
    },
    {
        TeamId: 2,
        TeamName: 'Cleveland Cavaliers',
        TeamPlayers: [
            {PlayerId: 1, PlayerName: 'Lebron James'},
            {PlayerId: 2, PlayerName: 'Kyrie Irving'},
            {PlayerId: 3, PlayerName: 'Anderson Varejao'},
            {PlayerId: 4, PlayerName: 'Dion Waiters'},
            {PlayerId: 5, PlayerName: 'Shawn Marion'}]
    },
    {
        TeamId: 3,
        TeamName: 'Los Angeles Clippers',
        TeamPlayers: [
            {PlayerId: 1, PlayerName: 'Chris Paul'},
            {PlayerId: 2, PlayerName: 'Blake Griffin'},
            {PlayerId: 3, PlayerName: 'DeAndre Jordan'},
            {PlayerId: 4, PlayerName: 'Jamal Crawford'},
            {PlayerId: 5, PlayerName: 'Matt Barnes'}]
    }
]
控制器:

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Description;
using MyApp.Models;

namespace MyApp.Controllers
{
    public class TeamsController : ApiController
    {
        private DataModel db = new DataModel();

        // GET: api/teams
        public IQueryable<TeamsWithPlayers> GetTeamsAndPlayers()
        {
            var query = from x in db.Teams
                        join y in db.Players on x.TeamId equals y.TeamId
                        select
                        {
                            // This is where I need some help...
                        }
        }
    }
}
球员级别:

namespace MyApp.Models
{
    public class Players 
    {
        public int TeamId { get; set; }
        public int PlayerId { get; set; }
        public string PlayerName { get; set; }
    }
}
有人能提供一些见解吗?

       var query = from x in db.Teams
        join y in db.Players on x.TeamId equals y.TeamId
        select new TeamsWithPlayers
        {
          TeamId = x.Id,
          TeamName= x.TeamName,
          Players = y
        }.ToList();
    
  • 我将假设JSON结构是事实的来源,而不是模型(TeamWithPlayer/Player)——请参阅我的评论

  • 我的解决方案假设您使用实体框架从数据库检索数据,因为我使用的是“Include”方法,但可以将其替换为使用“Join”

1-将TeamDto和PlayerDto类定义为:

public class TeamDto
{
    public int TeamId { get; set; }
    public string TeamName { get; set; }
    public IEnumerable<PlayerDto> TeamPlayers { get; set; }
}

public class PlayerDto
{
    public int PlayerId { get; set; }
    public string PlayerName { get; set; }
}
public class TeamDto
{
public int TeamId{get;set;}
公共字符串TeamName{get;set;}
public IEnumerable TeamPlayers{get;set;}
}
公营球员
{
public int PlayerId{get;set;}
公共字符串播放器名称{get;set;}
}
2-您的团队控制器如下所示:

public class TeamsController : ApiController
{
    private readonly TeamDbContext _dbContext = new TeamDbContext();

    // GET api/teams
    public IEnumerable<TeamDto> GetTeamsAndPlayers()
    {
        var teams = _dbContext
            .Teams
            .Include("Players") // Load the players associated with each Team, (this depends on your declaration, but you mentioned that there is a FK from Player => TeamId)
            // you can use the join if you like or if you don't use entity framework where you cannot call Include, but the following code will stay the same 
            .Select(t => new TeamDto
            {
                TeamId = t.TeamId,
                TeamName = t.TeamName,
                TeamPlayers = t.Players.Select(p => new PlayerDto
                    {
                        PlayerId = p.PlayerId, 
                        PlayerName = p.PlayerName
                    })
            }).ToList();

        return teams;
    }
}
公共类团队控制器:ApiController
{
private readonly TeamDbContext _dbContext=new TeamDbContext();
//获取api/团队
public IEnumerable GetTeamsAndPlayers()
{
var团队=_dbContext
.团队
.Include(“Players”)//加载与每个团队关联的玩家(这取决于您的声明,但您提到有一个FK from Player=>TeamId)
//如果您愿意或者不使用实体框架(不能调用Include),您可以使用join,但下面的代码将保持不变
.选择(t=>newteamdto
{
TeamId=t.TeamId,
TeamName=t.TeamName,
TeamPlayers=t.Players.选择(p=>newplayerdto
{
PlayerId=p.PlayerId,
PlayerName=p.PlayerName
})
}).ToList();
返回队;
}
}

希望有帮助。

喜欢建议的答案,非常有帮助

我使用建议的答案为msyelf制作了一个类似的解决方案,以供学习,然后尝试将上面的解决方案代码放入getbyid方法中

我经历了几次挣扎,但还是想出了以下可行的解决方案,以防有人像我一样偶然发现这篇文章,并想知道如何使用getbyid方法使用上述解决方案

以下是VS创建的默认WebAPI getbyid方法:

    // GET: api/teams/5
    [ResponseType(typeof(teams))]
    public IHttpActionResult Getteams(long id)
    {
        teams teams = db.teams.Find(id);
        if (teams == null)
        {
            return NotFound();
        }

       return Ok(teams);
    }
下面是更新后的Getbyid方法,它使用了本文中答案所用的结构:

    // GET: api/teams/5
    [ResponseType(typeof(teams))]
    public IHttpActionResult Getteams(long id)
    {
            var teams = _dbContext
            .Teams
            .Where(t => t.TeamId == id)
            .Include("Players")
            .Select(t => new TeamDto
            {
                TeamId = t.TeamId,
                TeamName = t.TeamName,
                TeamPlayers = t.Players.Select(p => new PlayerDto
                    {
                        PlayerId = p.PlayerId, 
                        PlayerName = p.PlayerName
                    })
            })
        });

        if (request == null)
        {
            return NotFound();
        }

        return Ok(requests);
    }

您的JSON结构与您的模型不匹配!在JSON中,您返回一个TeamPlayers数组,而您的TeamAndPlayers只有一个Player,但有命名的Players。您的查询不会返回所需的结构,请注意模型声明和查询,您会注意到您的查询在TeamsPlayer中返回TeamId,玩家不是一个集合。你能扩展你的答案来展示如果你没有FK关系会是什么样子吗。谢谢你,我说你真的很棒。非常感谢。
    // GET: api/teams/5
    [ResponseType(typeof(teams))]
    public IHttpActionResult Getteams(long id)
    {
            var teams = _dbContext
            .Teams
            .Where(t => t.TeamId == id)
            .Include("Players")
            .Select(t => new TeamDto
            {
                TeamId = t.TeamId,
                TeamName = t.TeamName,
                TeamPlayers = t.Players.Select(p => new PlayerDto
                    {
                        PlayerId = p.PlayerId, 
                        PlayerName = p.PlayerName
                    })
            })
        });

        if (request == null)
        {
            return NotFound();
        }

        return Ok(requests);
    }