Сделать группы сериализации для ASP.net core 2.1 API? - PullRequest
0 голосов
/ 20 июня 2019

Мне нужно сериализовать модель для 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
            );
        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...