I've a json string and a method to transform this into a DataTable, but nested objects isnt in DataTable.
MyJSON
[
{
"id": 645162,
"customerId": 9950,
"created": "2021-07-19T23:06:39.462913Z",
"updated": "2021-07-19T23:06:39.462913Z",
"createdBy": "System",
"updatedBy": "System",
"createdById": 0,
"updatedById": 0,
"checkId": 289960,
"cvssV2Score": 5,
"cvssV2BaseScore": 5,
"cvssV2Vector": "(AV:N/AC:L/Au:N/C:P/I:N/A:N)",
"cvssV2Severity": "MEDIUM",
"isAccepted": false,
"commentsCount": 0,
"source": [
"SCALE"
],
"name": "X-Frame-Options Header Missing or Malformed",
"description": "The clickjacking attack vector consists of an attacker creating a malicious web page that includes a section of the application within an <iframe>-element. The attacker cannot directly interact with the application, but they can control the main page and are able to overlay elements on top of the <iframe>. This can be leveraged in order to fool the end user that they are interacting with one page, when they are in reality interacting with another page.\n\nThe frameableness of a resource is determined by either the Content-Security-Policy header when used with the frame-ancestors directive, or using the X-Frame-Options header. \nBoth of these were missing or malformed on the found resource.",
"cwe": "CWE-1021",
"solution": "The Content-Security-Policy header with the frame-ancestors directive will resolve clickjacking in modern browsers that support it. Setting the frame-ancestors to 'self' (SAMEORIGIN) or 'none' (DENY) will limit which origins may frame this resource. Whitelisting external resources is possible using this method as well.\n\nTo ensure legacy client compatibility, set the X-Frame-Options header to either DENY (which means the resource can not be framed) or SAMEORIGIN (which means that only the same origin may frame this resource). Note that the 'allow-from' value is not implemented correctly in all browsers. If frameability in an external resource has to be permitted, use CSP.\n\nThese headers must be set on all server responses.",
"exploitAvailable": false,
"matchIds": [
707510
],
"firstSeen": "2021-07-19T23:06:39.462913Z",
"lastSeen": "2021-08-02T01:02:39.999Z",
"firstScanId": 585696,
"lastScanId": 602872,
"owasp2013": [
5
],
"owasp2017": [
6
],
"capec": [
103,
181,
222,
504,
506
],
"assetIdentifierId": 34431,
"assetIdentifierType": "IP",
"assetIdentifierName": "NOT TODAY",
"potential": false,
"softwareComponent": "Web Application Scanning",
"secureCodeWarrior": {
"name": "Improper Restriction of Rendered UI Layers or Frames",
"description": "The web application does not restrict or incorrectly restricts frame objects or UI layers that belong to another application or domain, which can lead to user confusion about which interface the user is interacting with.",
"url": "https://portal.securecodewarrior.com/?utm_source=partner-integration:scw#/website-trial/web/misconfig/securityfeatures/java/vanilla"
},
"tags": [
{
"id": 939,
"key": "UNKNOWN",
"value": "",
"inherited": true
}
]
}
]
MyMethod
public static DataTable ToDataTable<T>( this IList<T> list ) {
PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(T));
DataTable table = new DataTable();
//table.TableName = list.GetType().ReflectedType.Name;
for(int i = 0; i < props.Count; i++) {
PropertyDescriptor prop = props[i];
table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
}
object[] values = new object[props.Count];
foreach(T item in list) {
for(int i = 0; i < values.Length; i++)
values[i] = props[i].GetValue(item) ?? DBNull.Value;
table.Rows.Add(values);
}
return table;
}
My Object Class
public class RestFinding {
[JsonProperty("id")]
public int Id { get; set; }
[JsonProperty("customerId")]
public int CustomerId { get; set; }
[JsonProperty("created")]
public DateTime Created { get; set; }
[JsonProperty("updated")]
public DateTime Updated { get; set; }
[JsonProperty("createdBy")]
public string CreatedBy { get; set; }
[JsonProperty("updatedBy")]
public string UpdatedBy { get; set; }
[JsonProperty("createdById")]
public int CreatedById { get; set; }
[JsonProperty("updatedById")]
public int UpdatedById { get; set; }
[JsonProperty("checkId")]
public int CheckId { get; set; }
[JsonProperty("cvssV2Score")]
public double CvssV2Score { get; set; }
[JsonProperty("cvssV2BaseScore")]
public double CvssV2BaseScore { get; set; }
[JsonProperty("cvssV2Vector")]
public string CvssV2Vector { get; set; }
[JsonProperty("cvssV2Severity")]
public string CvssV2Severity { get; set; }
[JsonProperty("isAccepted")]
public bool IsAccepted { get; set; }
[JsonProperty("commentsCount")]
public int CommentsCount { get; set; }
[JsonProperty("source")]
public List<string> Source { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("description")]
public string Description { get; set; }
[JsonProperty("cwe")]
public string Cwe { get; set; }
[JsonProperty("solution")]
public string Solution { get; set; }
[JsonProperty("exploitAvailable")]
public bool ExploitAvailable { get; set; }
[JsonProperty("matchIds")]
public List<int> MatchIds { get; set; }
[JsonProperty("firstSeen")]
public DateTime FirstSeen { get; set; }
[JsonProperty("lastSeen")]
public DateTime LastSeen { get; set; }
[JsonProperty("firstScanId")]
public int FirstScanId { get; set; }
[JsonProperty("lastScanId")]
public int LastScanId { get; set; }
[JsonProperty("owasp2013")]
public List<int> Owasp2013 { get; set; }
[JsonProperty("owasp2017")]
public List<int> Owasp2017 { get; set; }
[JsonProperty("capec")]
public List<int> Capec { get; set; }
[JsonProperty("assetIdentifierId")]
public int AssetIdentifierId { get; set; }
[JsonProperty("assetIdentifierType")]
public string AssetIdentifierType { get; set; }
[JsonProperty("assetIdentifierName")]
public string AssetIdentifierName { get; set; }
[JsonProperty("potential")]
public bool Potential { get; set; }
[JsonProperty("softwareComponent")]
public string SoftwareComponent { get; set; }
[JsonProperty("secureCodeWarrior")]
public SecureCodeWarrior SecureCodeWarrior { get; set; }
[JsonProperty("tags")]
public List<Tag> Tags { get; set; }
[JsonProperty("cvssV3Score")]
public double? CvssV3Score { get; set; }
[JsonProperty("cvssV3BaseScore")]
public double? CvssV3BaseScore { get; set; }
[JsonProperty("cvssV3Vector")]
public string CvssV3Vector { get; set; }
[JsonProperty("cvssV3Severity")]
public string CvssV3Severity { get; set; }
[JsonProperty("wasc")]
public List<int> Wasc { get; set; }
[JsonProperty("owasp2010")]
public List<int> Owasp2010 { get; set; }
[JsonProperty("cve")]
public string Cve { get; set; }
[JsonProperty("sans25")]
public int? Sans25 { get; set; }
[JsonProperty("owasp2004")]
public List<int> Owasp2004 { get; set; }
[JsonProperty("owasp2007")]
public List<int> Owasp2007 { get; set; }
[JsonProperty("bugTraq")]
public List<int> BugTraq { get; set; }
}
public class Tag {
[JsonProperty("id")]
public int Id { get; set; }
[JsonProperty("key")]
public string Key { get; set; }
[JsonProperty("value")]
public string Value { get; set; }
[JsonProperty("inherited")]
public bool Inherited { get; set; }
}
Expected output of the nested object Tag is:
Tag_id | Tag_key | Tag_value
<int> | <string>| <string>
But my output is
SecureCodeWarrior | Tags | cvssV3Score
<string> | NULL | <string>
Is there a way to flatten json nested object as itemName_subitemName as mentioned? I've tried inumerous posts but dont return as mentioned...