Introduction
Ever faced a situation where you don't know what data is fed to your system/application? Ever felt the need to parse a dynamic json object, to bind it to some controls on your UI, or to convert it to a flat table or to a CSV? In case you are looking for a way to know what are the different fields in the json data received at your end, here's a solution on how to extract the fields from a json object.
Background
In the solution, using Newtonsoft.Json nuget to play with the json object. Making use of 'recursion' to drill down to nested fields of the json object. A recursive function to iterate through the json object, and to read Properties of the root element.
Using the Code
For a dynamic input json, return the list of all fields in that json object.
Step 1
Deserialize the Json to a .NET Object and navigate to the root element or the first element in case it's an Array.
input = Newtonsoft.Json.JsonConvert.DeserializeObject(input);
input = input.Root ?? input.First ?? input;
bool isArray = true;
while (isArray)
{
input = input.First ?? input;
if (input.GetType() == typeof(Newtonsoft.Json.Linq.JObject) ||
input.GetType() == typeof(Newtonsoft.Json.Linq.JValue) || input == null)
{
isArray = false;
}
}
Step 2
Once at the root level, read the Properties of the root object.
if (input.GetType() == typeof(Newtonsoft.Json.Linq.JObject))
{
Newtonsoft.Json.Linq.JObject inputJson = Newtonsoft.Json.Linq.JObject.FromObject(input);
var properties = inputJson.Properties();
}
Step 3
Iterate through all the Properties, and check if any Property
has values of type JObject
or JArray
. If yes, then that means it's a nested object. Pass the value of that property
to the same method (recursive) to read all properties of the nested object. If the value of Property
is not another JObject
or JArray
, read the name of the Property
; that name is the field name.
List<string> fieldNames = new List<string>();
foreach (var property in properties)
{
if (property.Value.GetType() == typeof(Newtonsoft.Json.Linq.JObject) ||
property.Value.GetType() == typeof(Newtonsoft.Json.Linq.JArray))
{
var subFields = GetFieldNames(property.Value.ToString());
if (subFields != null && subFields.Count() > 0)
{
fieldNames.AddRange(
subFields
.Select(n =>
string.IsNullOrEmpty(n) ? property.Name :
string.Format("{0}.{1}", property.Name, n)));
}
}
else
{
fieldNames.Add(property.Name);
}
}
Once all the properties are read and values checked, all field names are added to the List
of string
object.
Here's the complete code snippet:
public static List<string> GetFieldNames(dynamic input)
{
List<string> fieldNames = new List<string>();
try
{
input = Newtonsoft.Json.JsonConvert.DeserializeObject(input);
input = input.Root ?? input.First ?? input;
if (input != null)
{
bool isArray = true;
while (isArray)
{
input = input.First ?? input;
if (input.GetType() == typeof(Newtonsoft.Json.Linq.JObject) ||
input.GetType() == typeof(Newtonsoft.Json.Linq.JValue) ||
input == null)
isArray = false;
}
if (input.GetType() == typeof(Newtonsoft.Json.Linq.JObject))
{
Newtonsoft.Json.Linq.JObject inputJson =
Newtonsoft.Json.Linq.JObject.FromObject(input);
var properties = inputJson.Properties();
foreach (var property in properties)
{
if (property.Value.GetType() == typeof(Newtonsoft.Json.Linq.JObject) ||
property.Value.GetType() == typeof(Newtonsoft.Json.Linq.JArray))
{
var subFields = GetFieldNames(property.Value.ToString());
if (subFields != null && subFields.Count() > 0)
{
fieldNames.AddRange(
subFields
.Select(n =>
string.IsNullOrEmpty(n) ? property.Name :
string.Format("{0}.{1}", property.Name, n)));
}
}
else
{
fieldNames.Add(property.Name);
}
}
}
else
if (input.GetType() == typeof(Newtonsoft.Json.Linq.JValue))
{
fieldNames.Add(string.Empty);
}
}
}
catch
{
throw;
}
return fieldNames;
}
Example
Input
dynamic
{
"OfferId": "4E77902B-3A23-4A13-8699-90B23B58EE21",
"SubscriptionId": "844a7c65-5523-4aaf-9e17-6e223178ee51",
"EventType": "Purchase",
"SubscriptionStartDate": "2016-01-01T00:00:00Z",
"SubscriptionEndDate": "9999-12-31T23:59:59.9999999",
"SubscriptionLicenseCount": "25",
"IsTrial": "True",
"EmailRecipients": [{
"EmailAddresses": ["8IQ46/U36757n1apJJGILv4qjWyYV+1vR/GbJYx3QLg="],
"UserPrincipalName": "bI+KE5twJoPHZegYiJTFiQSMgeQ1+e0+vzw+ZmWE4SaTHXdxs/uqeY6hEWnCCEOk",
"FirstName": "pjUjsiidR28eBKH0NA7yEA==",
"LastName": "863qxqfQTSWpU3KJ/MlfMQ==",
"DisplayName": "Andrew S",
"UserCountry": "UK",
"OfferName": "30-Day Trial"
}]
}
Output
List<string>
OfferId
SubscriptionId
EventType
SubscriptionStartDate
SubscriptionEndDate
SubscriptionLicenseCount
IsTrial
EmailRecipients.EmailAddresses
EmailRecipients.UserPrincipalName
EmailRecipients.FirstName
EmailRecipients.LastName
EmailRecipients.DisplayName
EmailRecipients.UserCountry
EmailRecipients.OfferName