Harry Bilney
Harry Bilney

Reputation: 1

C# Getting number of items in a JSON array that is in another JSON Object

I'm trying to get the number of items in array "channels" which is inside an array called "modes". I've been easily able to get the name from the correct item in the "modes" array but now I need to get the number of items in the "channels" array.

Each "name" from the "modes" array is in a combobox names "cbxModes". I've tried having an if statement saying that is "name" is equal to "cbxModes.SelectedItem" then get number of items in "channels" from this item in "modes"

Here is my JSON

"modes": [
{
  "name": "1 – Standard 16bit RGBW",
  "shortName": "1-16bitRGBW",
  "channels": [
    "Pan",
    "Pan fine",
    "Tilt",
    "Tilt fine",
    "Pan/Tilt Speed",
    "Special Functions",
    "Virtual Color Wheel",
    "Red",
    "Red fine",
    "Green",
    "Green fine",
    "Blue",
    "Blue fine",
    "White",
    "White fine",
    "CTC",
    "Color Mix Control",
    "Zoom",
    "Zoom fine",
    "Shutter / Strobe",
    "Dimmer",
    "Dimmer fine"
  ]
},
{
  "name": "2 – Reduced 8bit RGBW",
  "shortName": "2-8bitRGBW",
  "channels": [
    "Pan",
    "Pan fine",
    "Tilt",
    "Tilt fine",
    "Pan/Tilt Speed",
    "Special Functions",
    "Virtual Color Wheel",
    "Red",
    "Green",
    "Blue",
    "White",
    "CTC",
    "Color Mix Control",
    "Zoom",
    "Dimmer"
  ]
},
{
  "name": "1 – Standard 16bit CMY",
  "shortName": "1-16bitCMY",
  "channels": [
    "Pan",
    "Pan fine",
    "Tilt",
    "Tilt fine",
    "Pan/Tilt Speed",
    "Special Functions",
    "Virtual Color Wheel",
    "Cyan",
    "Cyan fine",
    "Magenta",
    "Magenta fine",
    "Yellow",
    "Yellow fine",
    null,
    null,
    "CTC",
    "Color Mix Control",
    "Zoom",
    "Zoom fine",
    "Shutter / Strobe",
    "Dimmer",
    "Dimmer fine"
  ]
},
{
  "name": "2 – Reduced 8bit CMY",
  "shortName": "2-8bitCMY",
  "channels": [
    "Pan",
    "Pan fine",
    "Tilt",
    "Tilt fine",
    "Pan/Tilt Speed",
    "Special Functions",
    "Virtual Color Wheel",
    "Cyan",
    "Magenta",
    "Yellow",
    null,
    "CTC",
    "Color Mix Control",
    "Zoom",
    "Shutter / Strobe",
    "Dimmer"
  ]
}
],

This is my C#

private void CbxMode_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        string FixtureRoot = AppDomain.CurrentDomain.BaseDirectory + "Fixtures\\" + cbxManufacture.SelectedItem + "\\";

        string ModeRoot = null;

        var JSON_Mode_Count = (JObject)null;

        for (int i = 0; i < Directory.GetFiles(FixtureRoot).Length; i++)
        {
            var Fixtures = Directory.GetFiles(FixtureRoot);
            string Names = File.ReadAllText(Fixtures[i]);
            var JSON_Name = JsonConvert.DeserializeObject<dynamic>(Names);
            if (JSON_Name.name == cbxFixture.SelectedItem)
            {
                ModeRoot = AppDomain.CurrentDomain.BaseDirectory + "Fixtures\\" + cbxManufacture.SelectedItem + "\\" + JSON_Name.fixtureKey.ToString() + ".json";
                JSON_Mode_Count = JObject.Parse(File.ReadAllText(ModeRoot));

                JArray Modes = (JArray)JSON_Mode_Count["modes"];
                int numberOfModes = Modes.Count;

                string ModesJSON = File.ReadAllText(ModeRoot);
                var JSON_Mode = JsonConvert.DeserializeObject<dynamic>(ModesJSON);

                foreach (var obj in JSON_Mode.modes)
                {
                    foreach (var obj2 in obj.channels)
                    {
                        if (obj.name == cbxMode.SelectedItem)
                        {
                            JArray Channels = (JArray)JSON_Mode_Count["channels"];
                            int numberOfChannels = Channels.Count;

                            lblChannels.Content = numberOfChannels.ToString();
                        }
                    }

                }
            }
        }
    }

TIA

Upvotes: 0

Views: 400

Answers (3)

MindSwipe
MindSwipe

Reputation: 7940

There are tools available online for automagically generating classes from C# code, I however don't like them and prefer to it the manual way, so I'll show and try to explain the process.

JSON is structured, and everything in JSON is an object with properties. Here is a very simple example:

{
    "Name": "John",
    "Surname": "Doe"
}

This is valid JSON which represents an object with two Properties Name and Surname, the C# representation would be this:

public class Person
{
    public string Name {get; set;}
    public string Surname {get; set;}
}

Using Newtonsoft we can now deserialize our JSON to this Object like so:

JsonConvert.DeserializeObject<Person>(json);

This is the simplest form of JSON deserializing, we have no nested objects and no lists/ arrays. Now lets look at those:

{
    "Name": "John",
    "Surname": "Doe",
    "Children": [{
            "Name": "Jane",
            "Surname": "Doe"
        },
        {
            "Name": "Jack",
            "Surname": "Doe"
        }
    ]
}

This now contains a JSON Array ([ ... ]) of Objects. We can see these Objects are once again just people. So we can alter our person class to this:

public class Person
{
    public string Name {get; set;}
    public string Surname {get; set;}
    public List<Person> Children {get; set;}
}

Now lets get to your actual JSON. Looking at it this is the data structure I came up with:

public class Parent
{
    [JsonProperty("modes")]
    public List<Mode> Modes {get; set;}
}

public class Mode
{
    public string Name {get; set;}
    public string ShortName {get; set;}
    public List<string> Channels {get; set;}
}

You can now deserialize the JSON like so:

var deserialized = JsonConvert.DeserializeObject<Parent>(json);

I hope this helps you in future projects.

Edit: This won't fully work. I didn't see the "modes": [ at the start of the JSON, this means there is a Parent object which I know nothing of. I fixed the deserializing

Upvotes: 0

Ricardo Ara&#250;jo
Ricardo Ara&#250;jo

Reputation: 155

Try to map the json directly to a c# object that has direct correspondence to the json. Instead of doing JsonConvert.DeserializeObject<dynamic> do something like JsonConvert.DeserializeObject<ModesList> and your code will be a lot more simpler.

public class ModesList
{
    [JsonProperty("modes")]
    public List<Mode> Modes { get; set; }
}

public class Mode
{
    [JsonProperty("name")]

    public string Name { get; set; }

    [JsonProperty("shortName")]

    public string ShortName { get; set; }

    [JsonProperty("channels")]
    public List<string> Channels { get; set; }
}

Upvotes: 1

haldo
haldo

Reputation: 16711

It's usually easier to create a concrete model of your json as C# classes. You can create a model of your json on the following classes (using something like json2csharp.com or special paste into visual studio):

public class Mode
{
    public string Name { get; set; }
    public string ShortName { get; set; }
    public List<string> Channels { get; set; }
}

public class RootObject
{
    public List<Mode> Modes { get; set; }
}

Then you can deserialise using:

var data = JsonConvert.DeserializeObject<RootObject>(json);
foreach (var mode in data.Modes)
{
    var channels = mode.Channels;
    var channelCount = channels.Count();

    Console.WriteLine($"Name: {mode.Name}, Name: {mode.ShortName}, ChannelCount: {channelCount}"); 
}

Upvotes: 0

Related Questions