Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Extract Json Fields

0.00/5 (No votes)
9 Mar 2017 1  
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

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here