Мне нужно сериализовать модель для API.Моя модель STUDENT:
public abstract class Person
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public string FullName => LastName + ", " + FirstMidName;
public string Discriminator { get; set; }
}
public class Student : Person
{
public DateTime EnrollmentDate { get; set; }
public ICollection<Course> Courses { get; set; }
public Table Table { get; set; }
}
У меня есть сгенерированный контроллер из генератора кода Visual Studio:
[Route("api/[controller]")]
[ApiController]
public class StudentsController : ControllerBase
{
private readonly SchoolContext _context;
public StudentsController(SchoolContext context)
{
_context = context;
}
// GET: api/Students
[HttpGet]
public async Task<ActionResult<IEnumerable<Student>>> GetStudents()
{
return await _context.Students.ToListAsync();
}
}
И мне нужно создать "группы сериализации", например,в маршруте, который возвращает всех студентов, я не хочу отображать курсы.Но в маршруте, который возвращает конкретного студента, я хочу отобразить все курсы.
Лучшее решение, которое я нашел, - это создать собственный атрибут
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
sealed class SerializationGroup : Attribute
{
// See the attribute guidelines at
// http://go.microsoft.com/fwlink/?LinkId=85236
public SerializationGroup(string groupName)
{
this.GroupName = groupName;
}
public string GroupName { get; set; }
public static Dictionary<string, object> Filter<T>(T obj, List<string> groupList)
{
var resultObject = new Dictionary<string, object>();
PropertyInfo[] props = typeof(T).GetProperties();
foreach (PropertyInfo prop in props)
{
object[] attrs = prop.GetCustomAttributes(true);
foreach (object attr in attrs)
{
SerializationGroup serializationGroupFromProp = attr as SerializationGroup;
if (serializationGroupFromProp != null)
{
string groupName = serializationGroupFromProp.GroupName;
if (groupList.Contains(groupName))
{
resultObject.Add(prop.Name, prop.GetValue(obj));
}
}
}
}
return resultObject;
}
}
, который я добавляю в свойства
public abstract class Person
{
[SerializationGroup(Groups.DETAILS)]
public int ID { get; set; }
[SerializationGroup(Groups.LIST)]
[SerializationGroup(Groups.DETAILS)]
public string LastName { get; set; }
[SerializationGroup(Groups.LIST)]
[SerializationGroup(Groups.DETAILS)]
public string FirstMidName { get; set; }
[SerializationGroup(Groups.LIST)]
[SerializationGroup(Groups.DETAILS)]
public string FullName => LastName + ", " + FirstMidName;
[SerializationGroup(Groups.LIST)]
[SerializationGroup(Groups.DETAILS)]
[Column("Discriminator")]
public string Discriminator { get; set; }
}
public class Student : Person
{
[SerializationGroup(Groups.DETAILS)]
public DateTime EnrollmentDate { get; set; }
[SerializationGroup(Groups.DETAILS)]
public ICollection<Course> Courses { get; set; }
public Table Table { get; set; }
}
в этом случае у меня есть 2 группы: 1 для отображения списка, одна для отображения подробностей.
метод «filter» возвращает Dict<string, object>
, который представляетотфильтрованный объект, который будет сериализован
Но проблема в том, что этот метод не выполняет рекурсивную фильтрацию, и, кроме того, мне нужно выбрать группы для каждого подобъекта, которые мне нужно сериализовать.
Как я могу это сделать?Есть ли какой-нибудь пакет Nuget, который уже делает это?
Спасибо за любые ответы:)
Редактировать: Вот мой оригинальный маршрут:
[HttpGet]
public async Task<ActionResult<CustomResponse<FilteredObject>>> GetTodoItems(
[FromQuery] int? pageNumber
)
{
var students = from s in _context.Students select s;
var page = pageNumber ?? 1;
var pageSize = 3;
var result = await PaginatedList<Student>.CreateAsync(students, pageNumber ?? 1, pageSize);
var filteredStudents = new List<FilteredObject>();
foreach (var student in result)
{
filteredStudents.Add(SerializationGroup.Filter(student, new List<string>{Groups.LIST}));
}
return new CustomResponse<FilteredObject>(
page,
pageSize,
filteredStudents
);
}