I have CSV template file with different data files with filenames in below format that reads and store in CSVTemplate model
Note: The data is CSV file for each file types with names will be ordered.
id,FileType,FileName
1,Excel Files, Excel File 1
2,Excel Files, Excel File 2
3,Excel Files, Excel File 2.1
4,Document Files, Document File 1,
5,Document Files, Document File 2
6,Document Files, Document File 3
7,Document Files, Document File 3.1
8,Document Files, Document File 3.2
Model:
public class CSVTemplate
{
public int id { get; set; }
public string FileType{ get; set; }
public string FileName{ get; set; }
}
Code for reading CS Records: I am using CSVHelper NuGet package
public List<CSVTemplate> Fetch_TemplateData()
{
List<CSVTemplate> csvTemplateData = new List<CSVTemplate>();
try
{
string csvFilePath = @"File1.csv";
//CSVHelper Configuration Settings
var csvconfig = new CsvConfiguration(CultureInfo.InvariantCulture)
{
NewLine = Environment.NewLine,
HasHeaderRecord = true,
DetectDelimiterValues = new string[] { "," },
};
//Reading CSV File
using (var reader = new StreamReader(csvFilePath))
{
//Fetching CSV Records
using (var csv = new CsvReader(reader, csvconfig))
{
csvTemplateData = csv.GetRecords<CSVTemplate>().ToList();
}
};
return csvTemplateData;
}
catch (Exception)
{
throw;
}
}
I have below JSON response from WebAPI contains file names in title for all types of files which is nested and inner nested.
JSON:
{
"Field": [
{
"title": "Excel Files",
"Field": [
{
"title": "Excel File 1"
},
{
"title": "Excel File 2",
"Field": [
{
"title": "Excel File 2.1"
},
{
"title": "Excel File 2.2"
}
]
},
{
"title": "Excel File 3",
"Field": [
{
"title": "Excel File 3.1",
"Field": [
{
"title": "Excel File 3.1.1"
}
]
}
]
}
]
},
{
"title": "Document Files",
"Field": [
{
"title": "Document File 1"
},
{
"title": "Document File 2",
"Field": [
{
"title": "Document File 2.1"
},
{
"title": "Document File 2.2"
}
]
},
{
"title": "Document File 3",
"Field": [
{
"title": "Document File 3.1",
"Field": [
{
"title": "Document File 3.1.1"
}
]
}
]
}
]
}
]
}
CSV file contains mandatory file names of all file types. webapi response (json) contains mandatory and non mandatory file names. I need to compare CSV with webapi data and check if mandatory filenames are missed.
Model:
public class Field
{
public string title { get; set; }
public List<Field> Field { get; set; }
}
public class Root
{
public List<Field> Field { get; set; }
}
Updated Code:
public bool Validate_TemplateData(List<CSVTemplate> csvData)
{
bool isTemplateValidate = false;
try
{
string jsonFile = @".\json1.json";
string jsonString = File.ReadAllText(jsonFile);
Root jsondata = JsonConvert.DeserializeObject<Root>(jsonString);
if (jsondata != null)
{
bool isMatched = false;
foreach (var csvRowData in csvData)
{
var csvTitle = csvRowData.FileName;
foreach (var field in jsondata)
{
isMatched = CheckFieldTitle(field, 0, csvTitle);
if (isMatched)
{
break;
}
}
if (!isMatched)
{
Console.WriteLine($"Title : {csvTitle} Not matched.");
break;
}
}
}
}
catch (Exception)
{
throw;
}
return isTemplateValidate;
}
Recursive Function : to read all nested field names/titles from JSON.
private static bool CheckFieldTitle(Field field, int level, string csvTitle)
{
bool isTileMatched = false;
try
{
var fieldTitle = field.Title;
if (csvTitle.Trim().ToUpper().Equals(fieldTitle.Trim().ToUpper()))
{
Console.WriteLine($"Title: {csvTitle} Matched");
isTileMatched = true;
}
else
{
//check in Nested Fields
foreach (var subFields in field.Field)
{
isTileMatched = PrintSection(subSections, sectionLevel + 1, csvTitle);
if (isTileMatched)
{
return true;
}
}
}
}
catch (Exception)
{
isTileMatched = false;
throw;
}
return isTileMatched;
}
Output:
I want output which are missed in JSON data but available in CSV file.
Document File 3.2
Conditions:
If comparison failed at any level of loop with any file type, the rest of comparison should not proceed.
Example: Comparison failed at Excel File 2, so print Excel File 2 and stop comparison for all rest of files and file types.Comparison logic should be for each CSV row data with each web API response field title(json). It should not be like fetching entire JSON FileNames(Titles) as 1 list, and CSV Data(FileNames) as another list and do compare both list for differences.
Comparison should be Order of JSON data. (In this example, first compare all excel files and then Document Files)
Problem:
- The code is partially working but numerous of loops happening in recursive function which I would like to avoid.
Best Options:
To use any third party Nuget Packages (Object Comparison) for this kind of problem to optimize the code which I am unable to find.
Unable to do with LINQ query to optimize for each calls in solution.
I suggest you group the files by
FileTypefrom the JSON and then find the first missing CSV file.First, convert the JSON into a
Dictionaryby FileType and gather all the titles into aHashSet<string>:Then, convert the CSV file into a list of
CSVTemplate. I just did some simple code (not for production use):(
ToInt()is the obvious extension method.)Finally, you can find the first missing filename by checking each
CSVTemplatein order to see if it is present:firstMissingwill benullif no missing CSV FileName is found, otherwise it will contain the FileName. If you prefer, you can leave off the?.FileNameto get the first missingCSVTemplate.