使用linq将反序列化的json展平为"非正规化"名单

时间:2017-04-08 03:56:42

标签: c# linq

最终这只是一个基本的.net问题,但有一点背景:我正在尝试使用SQL Server Integration Services脚本组件从调查猴子的其余API中提取数据。因为这发生在SSIS中的脚本任务中并且在GAC中注册帮助程序库不是一种选择,所以第三方库和第三方SSIS工具都不在外面。显然这不是解决这个问题的理想方式,但这是我现在所困扰的。我能够毫无问题地提取我想要的json数据,每个数据都被反序列化为<SurveyDetail>类型的对象并添加到该类型的列表中。类:

public class SurveyDetail
        {
            public long? Id { get; set; }
            public string Title { get; set; }
            public string Nickname { get; set; }
            public string Category { get; set; }
            public string Language { get; set; }
            public int? Question_Count { get; set; }
            public DateTime? Date_Created { get; set; }
            public DateTime? Date_Modified { get; set; }  
            public List<Page> Pages { get; set; }             
        }

public class Page
        {
            public List<Question> Questions { get; set; }
        }

public class Question
        {
            public long? Id { get; set; }
            public string Title { get; set; }
            public QuestionFamily? Family { get; set; }
            public List<Headings> Headings { get; set; } 
            public QuestionAnswers Answers { get; set; }
        }

public class Headings
        {
            public string Heading { get; set; }
        }

public class QuestionAnswers
        {
            public List<Choice> Choices { get; set; }
        }

public class Choice
        {
            public long? Id { get; set; }
            public string Text { get; set; }      
        } 

所以给定List<SurveyDetail>,我想将其展平为List<SurveyQuestionOption>以便于登台进入数据库:

public class SurveyQuestionOption
    {
        public long? SurveyID { get; set; }
        public string SurveyTitle { get; set; }
        public DateTime? DateCreated { get; set; }
        public DateTime? DateModified { get; set; }
        public long? QuestionID { get; set; }
        public string QuestionTitle { get; set; }
        public string QuestionType { get; set; }
        public string QuestionText { get; set; }
        public long? AnswerOptionID { get; set; }
        public string AnswerOptionText { get; set; }
    }

绊脚石似乎是<QuestionAnswers>中的<Question>对象有时可能为空,我的目标是在<SurveyQuestionOption>中有空值,在这种情况下,但是当我尝试这样做时,我得到空引用异常:

List<SurveyQuestionOption> flatData = new List<SurveyQuestionOption>();

    flatData = (from s in surveyDetails
                    from p in s.Pages
                    from q in p.Questions
                    from h in q.Headings.DefaultIfEmpty()
                    from c in q.Answers.Choices.DefaultIfEmpty()
                    select new SurveyQuestionOption
                    {
                        SurveyID = s.Id == null ? null : s.Id,
                        SurveyTitle = s.Title == null ? null : s.Title,
                        DateCreated = s.Date_Created == null ? null : s.Date_Created,
                        DateModified = s.Date_Modified == null ? null : s.Date_Modified,
                        QuestionID = q.Id == null ? null : q.Id,
                        QuestionTitle = q.Title == null ? null : q.Title,
                        QuestionType = q.Family.Value.ToString(),
                        QuestionText = h.Heading.FirstOrDefault().ToString() == null ? null : h.Heading.FirstOrDefault().ToString(),
                        AnswerOptionID = c.Id == null ? null : c.Id,
                        AnswerOptionText = c.Text == null ? null : c.Text
                    }).ToList<SurveyQuestionOption>();

我知道有类似的问题已被提出,但我仍然在努力让查询适合我的特定情况。我显然不是一个交易的.net开发者。任何帮助非常感谢。

1 个答案:

答案 0 :(得分:0)

我能够通过显式构造函数为<Question>类型的无效成员解决这个问题,并为DeafultIfEmpty提供<Choice>的新实例,如下所示:

public class Question
{
    public long? Id { get; set; }
    public string Title { get; set; }
    public QuestionFamily? Family { get; set; }
    public List<Headings> Headings { get; set; }
    public string Heading { get; set; } 
    public bool? Visible { get; set; }
    public bool? ForcedRanking { get; set; }
    internal string Href { get; set; }
    public QuestionAnswers Answers { get; set; }
    public string Nickname { get; set; }

    public Question()
    {
        Answers = new QuestionAnswers();
    }
}

public class QuestionAnswers
{
    public List<Choice> Choices { get; set; }
    public OtherAnswer Other { get; set; }

    public QuestionAnswers()
    {
        Choices = new List<Choice>();
    }
}



flatData = (from s in surveyDetails
                    from p in s.Pages
                    from q in p.Questions
                    from h in q.Headings.DefaultIfEmpty()
                    from c in q.Answers.Choices.DefaultIfEmpty(new Choice())
                    select new SurveyQuestionOption
                    {
                        SurveyID = s.Id == null ? null : s.Id,
                        SurveyTitle = s.Title == null ? null : s.Title,
                        DateCreated = s.Date_Created == null ? null : s.Date_Created,
                        DateModified = s.Date_Modified == null ? null : s.Date_Modified,
                        QuestionID = q.Id == null ? null : q.Id,
                        QuestionTitle = q.Title == null ? null : q.Title,
                        QuestionType = q.Family.Value.ToString(),
                        QuestionText = h.Heading.FirstOrDefault().ToString() == null ? null : h.Heading.FirstOrDefault().ToString(),
                        AnswerOptionID = c.Id == null ? null : c.Id,
                        AnswerOptionText = c.Text == null ? null : c.Text
                    }).ToList<SurveyQuestionOption>();