【问题标题】:Web API Returning Nested JSON ValuesWeb API 返回嵌套的 JSON 值
【发布时间】:2015-02-03 21:12:23
【问题描述】:

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

比如说,我有两张桌子,TeamsPlayers。他们由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...
                        }
        }
    }
}

TeamAndPlayer 类:

namespace MyApp.Models
{
    public class TeamAndPlayers
    {
        public int TeamId { get; set; }
        public string TeamName { get; set; }
        public Players players { get; set; }
    }
}

玩家类:

namespace MyApp.Models
{
    public class Players 
    {
        public int TeamId { get; set; }
        public int PlayerId { get; set; }
        public string PlayerName { get; set; }
    }
}

有人可以提供一些见解吗?

【问题讨论】:

  • 您的 JSON 结构与您的模型不匹配!在 JSON 中,您返回一个 TeamPlayers 数组,而您的 TeamAndPlayers 有一个 Player,但名为 Players。

标签: c# sql json asp.net-web-api


【解决方案1】:
   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();

【讨论】:

  • 你的查询不会返回所需的结构,注意模型声明和你的查询,你会注意到你的查询返回的是TeamsPlayer中的TeamId,而Players不是一个集合。
【解决方案2】:
  • 我将假设 JSON 结构是此处的真实来源,而不是模型 (TeamWithPlayers/Players) - 请参阅我的 cmets。

  • 我的解决方案假定您正在使用实体框架从数据库中检索数据,因为我使用的是“包含”方法,但可以将其替换为使用“加入”。

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; }
}

2- 您的 TeamsController 将如下所示:

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;
    }
}

希望对您有所帮助。

【讨论】:

  • 能否请您扩展您的答案以显示如果您没有 FK 关系会是什么样子。谢谢
  • 我的朋友说你真的很棒。谢谢。
【解决方案3】:

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

我使用建议的答案为 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);
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-20
    • 1970-01-01
    • 2020-10-23
    • 2021-04-25
    • 2017-03-15
    • 1970-01-01
    • 1970-01-01
    • 2013-02-04
    相关资源
    最近更新 更多