Deserialize/Parse JSON and use it for LOOKUP

I am trying to read in a JSON  stream and able to use it to look up the datatype of a property. please see below.
What do I need to call using JSON.net to structure a proper lookup of an array of elements,  Below is a summary what I would like to do:
1. Lookup to see if there is a match of one of the following keyword:- 'Device/AnalogInput/AnalogOutput ...'.  This list can vary at runtime hence I can not write a class for each keyword
2. if exist,  loop through the property to find out the data type of each property
For example
I check if there is a keyword called 'Device',  Once I find it exists, I would like to loop through to find the 'datatype' of each property. In this case, I would find out 'datatype' of property 'SystemStatus' is 'int'. Next, I would find out 'datatype' of property 'ObjectName' is 'string'.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Data;


namespace TestJSONLookup
{
    class Program
    {
        static void Main(string[] args)
        {
            string json = @"[
  {
    'Device': [
      {
        'property': 'SystemStatus',
        'dataType': 'int'
      },
      {
        'property': 'ObjectName',
        'dataType': 'string'
      }
    ]
  },
  {
    'AnalogInput': [
      {
        'property': 'PresentValue',
        'type': 'real'
      }
    ]
  },
  {
    'AnalogOutput' : [
      {
        'property': 'PresentValue',
        'type': 'real'
      }
    ]
	},
	{
		'AnalogValue': [
			{ 'property': 'PresentValue', 'type': 'real' },
			{ 'property': 'Status', 'type': 'int' }
		]
	},
	{
		'BinaryInput' : [
			{ 'property': 'PresentValue', 'type': 'bool' }					
		]
	},
  {
		'BinaryOutput' : [
			{ 'property': 'PresentValue', 'type': 'bool' }					
		]
	},
	{
		'BinaryValue' : [
			{ 'property': 'PresentValue', 'type': 'bool' }
		]
	},
	{
		'MultistateInput' : [
			{ 'property': 'PresentValue', 'type': 'real' }					
		]
  },
	{	
		'MultistateOutput' : [
			{ 'property': 'PresentValue', 'type': 'real' }					
		]
	},
	{
		'MultistateValue' : [
			{ 'property': 'PresentValue', 'type': 'real' },
			{ 'property': 'Status', 'type': 'int' }
		]
	}
]";

            a = JArray.Parse(json);
            // not sure what is next statement to setup the lookup
            //JToken t = a[0];
            //JObject o = t;
            //Console.WriteLine(a.ToString());
        }
    }
}

Open in new window

tommym121Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

it_saigeDeveloperCommented:
You could do something like this:
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace EE_Q29124178
{
	class Program
	{
		static string json = @"[{
			'Device':[{
				'property':'SystemStatus',
				'dataType':'int'
			},{
				'property':'ObjectName',
				'dataType':'string'
			}]
		},{
			'AnalogInput':[{
				'property':'PresentValue',
				'dataType':'real'
			}]
		},{
			'AnalogOutput':[{
				'property':'PresentValue',
				'dataType':'real'
			}]
		},{
			'AnalogValue':[{
				'property':'PresentValue',
				'dataType':'real'
			},{
				'property':'Status',
				'dataType':'int'
			}]
		},{
			'BinaryInput':[{
				'property':'PresentValue',
				'dataType':'bool'
			}]
		},{
			'BinaryOutput':[{
				'property':'PresentValue',
				'dataType':'bool'
			}]
		},{
			'BinaryValue':[{
				'property':'PresentValue',
				'dataType':'bool'
			}]
		},{
			'MultistateInput':[{
				'property':'PresentValue',
				'dataType':'real'
			}]
		},{
			'MultistateOutput':[{
				'property':'PresentValue',
				'dataType':'real'
			}]
		},{
			'MultistateValue':[{
				'property':'PresentValue',
				'dataType':'real'
			},{
				'property':'Status',
				'dataType':'int'
			}]
		}]";

		static void Main(string[] args)
		{
			var keywords = @"Device/AnalogInput/AnalogOutput";
			var terms = keywords.Split('/');
			var definitions = Newtonsoft.Json.JsonConvert.DeserializeObject<JObject[]>(json);
			var results = (from term in terms
						   from definition in definitions.Where(d => d.ContainsKey(term))
						   from child in definition[term].Children()
						   group child by term into grp
						   select new KeyValuePair<string, List<Definition>>(grp.Key, (from d in grp select new Definition { Property = d["property"].Value<string>(), DataType = d["dataType"].Value<string>() }).ToList())).ToDictionary(k => k.Key, v => v.Value);
			foreach (var result in results)
			{
				foreach (var definition in result.Value)
				{
					Console.WriteLine($"Key: {result.Key}; Value: {definition}");
				}
			}
			Console.ReadLine();
		}
	}

	class Definition
	{
		public string Property { get; set; }
		public string DataType { get; set; }

		public override string ToString()
		{
			return $"{{ {string.Join(", ", from prop in GetType().GetProperties() select $"{prop.Name}: {prop.GetValue(this, null)}")} }}";
		}
	}
}

Open in new window

Which produces the following output -Capture.PNG-saige-
it_saigeDeveloperCommented:
Another option would be just to create a dictionary from the JSON and then simply get the List of definitions from the key; e.g. -
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace EE_Q29124178
{
	class Program
	{
		static string json = @"[{
			'Device':[{
				'property':'SystemStatus',
				'dataType':'int'
			},{
				'property':'ObjectName',
				'dataType':'string'
			}]
		},{
			'AnalogInput':[{
				'property':'PresentValue',
				'dataType':'real'
			}]
		},{
			'AnalogOutput':[{
				'property':'PresentValue',
				'dataType':'real'
			}]
		},{
			'AnalogValue':[{
				'property':'PresentValue',
				'dataType':'real'
			},{
				'property':'Status',
				'dataType':'int'
			}]
		},{
			'BinaryInput':[{
				'property':'PresentValue',
				'dataType':'bool'
			}]
		},{
			'BinaryOutput':[{
				'property':'PresentValue',
				'dataType':'bool'
			}]
		},{
			'BinaryValue':[{
				'property':'PresentValue',
				'dataType':'bool'
			}]
		},{
			'MultistateInput':[{
				'property':'PresentValue',
				'dataType':'real'
			}]
		},{
			'MultistateOutput':[{
				'property':'PresentValue',
				'dataType':'real'
			}]
		},{
			'MultistateValue':[{
				'property':'PresentValue',
				'dataType':'real'
			},{
				'property':'Status',
				'dataType':'int'
			}]
		}]";

		static void Main(string[] args)
		{
			var keywords = @"Device/AnalogInput/AnalogOutput";
			var terms = keywords.Split('/');
			var sets = Newtonsoft.Json.JsonConvert.DeserializeObject<JObject[]>(json);
			var dictionary = (from set in sets
							  let term = set.Properties().First().Name
							  from child in set[term].Children()
							  group child by term into grp
							  select new KeyValuePair<string, List<Definition>>(grp.Key, (from d in grp select new Definition { Property = d["property"].Value<string>(), DataType = d["dataType"].Value<string>() }).ToList())).ToDictionary(k => k.Key, v => v.Value);

			foreach (var term in terms)
			{
				List<Definition> definitions;
				if (dictionary.TryGetValue(term, out definitions))
				{
					foreach (var definition in definitions)
					{
						Console.WriteLine($"Key: {term}; Value: {definition}");
					}
				}
				else
				{
					Console.WriteLine($"Dictionary contained no values for {term}");
				}
			}
			Console.ReadLine();
		}
	}

	class Definition
	{
		public string Property { get; set; }
		public string DataType { get; set; }

		public override string ToString()
		{
			return $"{{ {string.Join(", ", from prop in GetType().GetProperties() select $"{prop.Name}: {prop.GetValue(this, null)}")} }}";
		}
	}
}

Open in new window

Which would produce the same output as above.

-saige-

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
tommym121Author Commented:
Thank you.  This is what I miss.   If you have a moment, please give me some explanation on what this statement work.  Some good reference to explain this kind of structures will be good.  Thanks for your help.  

var dictionary = (from set in sets
                                            let term = set.Properties().First().Name
                                            from child in set[term].Children()
                                            group child by term into grp
                                            select new KeyValuePair<string, List<Definition>>(grp.Key, (from d in grp select new Definition { Property = d["property"].Value<string>(), DataType = d["dataType"].Value<string>() }).ToList())).ToDictionary(k => k.Key, v => v.Value);
it_saigeDeveloperCommented:
This is a LINQ statment.  Here is the same logic written without using LINQ:
var dictionary = new Dictionary<string, List<Definition>>();
foreach (var set in sets)
{
	var term = set.Properties().First().Name;
	var grp = new List<Definition>();
	foreach (var child in set[term].Children())
	{
		grp.Add(new Definition { Property = child["property"].Value<string>(), DataType = child["property"].Value<string>() });
	}
	dictionary.Add(term, grp);
}

Open in new window

-saige-
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C#

From novice to tech pro — start learning today.