Click here to Skip to main content
15,886,673 members
Articles / Programming Languages / C#
Tip/Trick

Extract Json Fields

Rate me:
Please Sign up or sign in to vote.
4.33/5 (7 votes)
9 Mar 2017CPOL1 min read 56.4K   11   15
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.

JavaScript
// 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.

JavaScript
// 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.

JavaScript
// 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:

JavaScript
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

JavaScript
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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralSame... ish.. Pin
Robert Bettinelli16-Mar-17 10:32
Robert Bettinelli16-Mar-17 10:32 
Questioneficiency ? Pin
mag1311-Mar-17 3:37
mag1311-Mar-17 3:37 
AnswerMessage Closed Pin
11-Mar-17 4:45
TarunSingla11-Mar-17 4:45 
GeneralRe: eficiency ? Pin
mag1311-Mar-17 4:57
mag1311-Mar-17 4:57 
wow you read the lines, Wink | ;) now you can use MSDN for best practice. Do you want working code ? this is not free. Do you want direction ? you receive that. Don't tell me that hyou know that, your 100 line of code prove else (time is money), now you know what to apply. I think you know to integrate my example in one simple recursive function. or not ? D'Oh! | :doh:
magsoft

AnswerRe: eficiency ? Pin
John B Oliver14-Mar-17 15:01
John B Oliver14-Mar-17 15:01 
GeneralRe: eficiency ? Pin
mag1315-Mar-17 11:22
mag1315-Mar-17 11:22 
GeneralRe: eficiency ? Pin
John B Oliver15-Mar-17 11:30
John B Oliver15-Mar-17 11:30 
GeneralRe: eficiency ? Pin
mag1315-Mar-17 13:30
mag1315-Mar-17 13:30 
GeneralRe: eficiency ? Pin
John B Oliver15-Mar-17 14:31
John B Oliver15-Mar-17 14:31 
GeneralRe: eficiency ? Pin
mag1316-Mar-17 0:51
mag1316-Mar-17 0:51 
GeneralRe: eficiency ? Pin
mag1316-Mar-17 2:01
mag1316-Mar-17 2:01 
GeneralRe: eficiency ? Pin
John B Oliver16-Mar-17 9:50
John B Oliver16-Mar-17 9:50 
GeneralRe: eficiency ? Pin
mag1316-Mar-17 10:49
mag1316-Mar-17 10:49 
Questionlove it Pin
mjhassan10-Mar-17 23:23
professionalmjhassan10-Mar-17 23:23 
PraiseCool. Pin
jmptrader10-Mar-17 7:35
professionaljmptrader10-Mar-17 7:35 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.