I am working with .NET Core and building an API. I have incoming JSON which I'm mapping to C# objects, and for the most part the JSON is quite simple, except one section which potentially has an array within an array, see below:
"marketing_preferences": [
{
"channel": "EDM",
"opt_in": false,
"valid_from_date": "2020-05-30T07:07:53.723Z",
"content_type_preferences": [
{
"type": "CAT",
"opt_in": false,
"valid_from_date": "2020-05-30T07:07:53.724Z"
},
{
"type": "TAC",
"opt_in": true,
"valid_from_date": "2020-05-30T07:07:53.724Z"
}
]
},
{
"channel": "SMS",
"opt_in": true,
"valid_from_date": "2020-05-30T07:07:53.724Z",
"content_type_preferences": []
},
{
"channel": "SM",
"opt_in": true,
"valid_from_date": "2020-05-30T07:07:53.724Z",
"content_type_preferences": []
}
]
Marketing preferences may (but may not) contain one or more content_type_preferences. So marketing_preferences is an array, and content_type_preferences is an optional array within that array. Mapping or projecting marketing preferences within my code is simple enough:
customer.MarketingPreferences = source.RequestCustomer.MarketingPreferences
.Select(x => new MarketingPreferences()
{
ChannelId = x.Channel,
OptIn = x.OptIn,
ValidFromDate = x.ValidFromDate,
UpdatedBy = Functions.DbUser,
CreatedDate = DateTime.UtcNow,
UpdatedDate = DateTime.UtcNow,
UpdatingStore = null // Not passed by API
})
.ToList();
However I'm a bit stuck on the syntax to project the content_type_preferences onto their equivalent object. Here are the classes I'm trying to project to:
public partial class MarketingPreferences
{
public MarketingPreferences()
{
ContentTypePreferences = new HashSet<ContentTypePreferences>();
}
public Guid CustomerInternalId { get; set; }
public string ChannelId { get; set; }
public bool? OptIn { get; set; }
public DateTime? ValidFromDate { get; set; }
public string UpdatedBy { get; set; }
public DateTime? CreatedDate { get; set; }
public DateTime? UpdatedDate { get; set; }
public string UpdatingStore { get; set; }
public virtual Customer CustomerInternal { get; set; }
public virtual ICollection<ContentTypePreferences> ContentTypePreferences { get; set; }
}
and
public partial class ContentTypePreferences
{
public Guid CustomerInternalId { get; set; }
public string ChannelId { get; set; }
public string TypeId { get; set; }
public bool? OptIn { get; set; }
public DateTime? CreatedDate { get; set; }
public DateTime? UpdatedDate { get; set; }
public DateTime? ValidFromDate { get; set; }
public string UpdatedBy { get; set; }
public string UpdatingStore { get; set; }
public virtual MarketingPreferences C { get; set; }
public virtual Customer CustomerInternal { get; set; }
}
I did start to revert to a clunky way of doing it, but I'm really not happy with it and would prefer to try and find the LINQ-ish way to achieve the below:
foreach (var marketingPrefs in source.RequestCustomer.MarketingPreferences)
{
if (marketingPrefs.ContentTypePreferences.Length > 0)
{
Console.WriteLine($"marketing preference: {marketingPrefs.Channel}");
foreach (var contentPrefs in marketingPrefs.ContentTypePreferences)
{
Console.WriteLine($"content preference: {contentPrefs.Type}");
customer.ContentTypePreferences.Add(new ContentTypePreferences
{
TypeId = contentPrefs.Type,
OptIn = contentPrefs.OptIn,
ValidFromDate = contentPrefs.ValidFromDate
});
}
}
}