linq查询其中一些值可能会丢失

时间:2018-01-01 17:43:40

标签: c# linq json.net

我从JSON中提取联系人,数据中的联系人可能包含电子邮件和电话号码。

如果他们这样做,则以下查询完美运行:

var results = from d in json.Data
                from c in d.Contacts
                from e in c.Emails
                from p in c.Phones
                select new IoModel {Email = e.EmailValue, Id = d.Id, FullName = string.IsNullOrEmpty(c.Name) ? c.Name : d.DisplayName, Phone = p.PhoneNumber, DOB = d.CustomDOB};

如果数据没有电子邮件或电话,那么它运行时没有错误,但它不会返回联系人姓名。

有没有办法在不使用if和and来保持代码更短更清洁的情况下执行此操作?

以下是缺少电子邮件的JSON示例:

{
    "data": [
        {
            "addresses": [], 
            "contacts": [
                {
                    "created_by": "user_ltUL3eXGPRWb5ghDeGTfOe9qjW0LeE2e4ouopLcSSWj", 
                    "date_created": "2017-12-28T17:13:00.392000+00:00", 
                    "date_updated": "2017-12-28T17:13:58.453000+00:00", 
                    "emails": [], 
                    "id": "cont_6hxxhz51ctlTnHfo8gA8cce0rthS1dJy1kguKAj148s", 
                    "integration_links": [
                        {
                            "name": "LinkedIn Search", 
                            "url": "https://www.linkedin.com/search/results/index/?keywords=John%20Doe"
                        }
                    ], 
                    "lead_id": "lead_3UzfxCgQHmw4BlGwElitHhlP6E7q9Tg3sdSkTl1CIXp", 
                    "name": "John Doe", 
                    "organization_id": "orga_PvgGx1opSZDsCHl73P8OoSFZUlJ3qsNGI2kwgoObM17", 
                    "phones": [
                        {
                            "phone": "+15555555555", 
                            "phone_formatted": "+1 555-555-5555", 
                            "type": "mobile"
                        }
                    ], 
                    "title": "Main Service", 
                    "updated_by": "user_ltUL3eXXPRWb5shDeGTfOe9qjP0LeE2e4ouopLcSSWj", 
                    "urls": []
                }
            ], 
            "created_by": "user_ltUL3eXXPRWb5shDeGTfOe9qjW0LeE2e4ouopLcSSWP", 
            "created_by_name": "John", 
            "custom": {
                "Date Of Birth": "1901-08-01", 
                "Department": "Main Service", 
                "Initial Service": "Main Service"
            }, 
            "custom.lcf_ufMH5ZhlR99zcdvJxKMxdgxcIbV4wtgTb3EdWDEkL8g": "1971-08-17", 
            "date_created": "2017-12-28T17:13:00.388000+00:00", 
            "date_updated": "2017-12-29T21:41:53.840000+00:00", 
            "description": "", 
            "display_name": "John Doe", 
            "html_url": "https://app.close.io/lead/lead_3UzfxCgQHmw4BlGwElitHhlP6E7q9Tg3sdSkTl1CIXp/", 
            "id": "lead_3UzfxCgQHmw4BlGwElitHhlP5E7q9Tg3sdSkTl1CIXp", 
            "integration_links": [
                {
                    "name": "Google Search", 
                    "url": "http://google.com/search?q=John%20Doe"
                }
            ], 
            "name": "", 
            "opportunities": [], 
            "organization_id": "orga_AvcGx4opSZDsCHl73H8OogDDUlJ3qsNGI2kwgoObA17", 
            "status_id": "stat_LpJu8FO72WgIob4qDDVnS4GEieoU41zmQ8xBquTvusm", 
            "status_label": "Established Patient", 
            "tasks": [], 
            "updated_by": "user_0JFRnl8QRvRhMhAlLz4JJxgmrzPeLs3xboxYyj5Pm80", 
            "updated_by_name": "BT", 
            "url": null
        }
    ], 
    "has_more": false, 
    "total_results": 1
}

2 个答案:

答案 0 :(得分:2)

由于我不知道你要将你的JSON反序列化,我只能在这里猜测一个解决方案,但我想如果你在DefaultIfEmpty()和{{1}上使用Emails收集然后在PhonesEmailValue上使用空条件运算符,你应该得到你想要的结果:

PhoneNumber

答案 1 :(得分:2)

让我解释一下你遇到的问题。想象一下以下两个列表:

<强>问题

var ids = new List<int> { 1, 2, 3, 4 };
var names = new List<string>();

让我们编写一个Linq查询来获取所有id以及名称:

var idsAndNames = from id in ids
                  from name in names
                  select new { Id = id, Name = name };

以上查询将不返回任何结果。为什么?如果您使用foreach而不是Linq,则更为明显。 foreach版本大致如下所示:

foreach (var id in ids)
{
    foreach (var name in names)
    {
        //select new { Id = id, Name = name };
    }
}

很清楚也很明显为什么在上面的foreach版本中不会返回任何结果(内部循环中的代码将不会被执行,因为names列表为空)。

<强>修正

我们需要告诉我们的查询:如果names集合中没有项目,我们将接受默认。我们可以使用DefaultIfEmpty方法做到这一点。

var idsAndNames = from id in ids
                  from name in names.DefaultIfEmpty()
                  select new { Id = id, Name = name };

以上将返回4个结果。这有点像执行以下操作:

foreach (var id in ids)
{
    if (names.Any())
    {
        //select new { Id = id, Name = name };
    }
    else
    {
        //select new { Id = id, Name = "" }; // <-- Notice empty string
    }
}

回答您的问题

@BrianRogers已经回答了你的问题,但我详细说明了问题所在。