Extract Json Fields






4.33/5 (7 votes)
How to extract field names from json?
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.
// Deserialize the input json string to an object
input = Newtonsoft.Json.JsonConvert.DeserializeObject(input);
// Json Object could either contain an array or an object or just values.
// To get the field names, parse the first element of the Array
input = input.Root ?? input.First ?? input;
// Get to the first element in the array
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.
// check if the object is of type JObject. If yes, read the properties of that JObject
if (input.GetType() == typeof(Newtonsoft.Json.Linq.JObject))
{
// Create JObject from object
Newtonsoft.Json.Linq.JObject inputJson = Newtonsoft.Json.Linq.JObject.FromObject(input);
// Read Properties of the JObject
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.
// use List of string, to store the output
List<string> fieldNames = new List<string>();
// Loop through all the properties of that JObject
foreach (var property in properties)
{
// Check if there are any sub-fields (nested)
// i.e. the value of any field is another JObject or another JArray
if (property.Value.GetType() == typeof(Newtonsoft.Json.Linq.JObject) ||
property.Value.GetType() == typeof(Newtonsoft.Json.Linq.JArray))
{
// If yes, enter the recursive loop to extract sub-field names
var subFields = GetFieldNames(property.Value.ToString());
if (subFields != null && subFields.Count() > 0)
{
// join sub-field names with field name
// (e.g. Field1.SubField1, Field1.SubField2, etc.)
fieldNames.AddRange(
subFields
.Select(n =>
string.IsNullOrEmpty(n) ? property.Name :
string.Format("{0}.{1}", property.Name, n)));
}
}
else
{
// If there are no sub-fields, the property name is the field name
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
{
// Deserialize the input json string to an object
input = Newtonsoft.Json.JsonConvert.DeserializeObject(input);
// Json Object could either contain an array or an object or just values
// For the field names, navigate to the root or the first element
input = input.Root ?? input.First ?? input;
if (input != null)
{
// Get to the first element in the array
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;
}
// check if the object is of type JObject.
// If yes, read the properties of that JObject
if (input.GetType() == typeof(Newtonsoft.Json.Linq.JObject))
{
// Create JObject from object
Newtonsoft.Json.Linq.JObject inputJson =
Newtonsoft.Json.Linq.JObject.FromObject(input);
// Read Properties
var properties = inputJson.Properties();
// Loop through all the properties of that JObject
foreach (var property in properties)
{
// Check if there are any sub-fields (nested)
// i.e. the value of any field is another JObject or another JArray
if (property.Value.GetType() == typeof(Newtonsoft.Json.Linq.JObject) ||
property.Value.GetType() == typeof(Newtonsoft.Json.Linq.JArray))
{
// If yes, enter the recursive loop to extract sub-field names
var subFields = GetFieldNames(property.Value.ToString());
if (subFields != null && subFields.Count() > 0)
{
// join sub-field names with field name
//(e.g. Field1.SubField1, Field1.SubField2, etc.)
fieldNames.AddRange(
subFields
.Select(n =>
string.IsNullOrEmpty(n) ? property.Name :
string.Format("{0}.{1}", property.Name, n)));
}
}
else
{
// If there are no sub-fields, the property name is the field name
fieldNames.Add(property.Name);
}
}
}
else
if (input.GetType() == typeof(Newtonsoft.Json.Linq.JValue))
{
// for direct values, there is no field name
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