Brent Barbata
Brent Barbata

Reputation: 3641

Count Number of Elements in JSON string with Json.NET in C#

I have a JSON string that looks like this:

{
"package1": {
    "type": "envelope",
    "quantity": 1,
    "length": 6,
    "width": 1,
    "height": 4
},
"package2": {
    "type": "box",
    "quantity": 2,
    "length": 9,
    "width": 9,
    "height": 9
}
}

I'm using the Json.NET LINQ to JSON functionality to handle my JSON string, but I'm wondering how I can find the total number of nodes/elements/keys (I'm not really sure what to call them) in my string. For example, the above string has package1 and package2 so I'm wondering how I can get it to return the integer 2. Sometimes I might only have one package, in which case, I'd like it to return the integer 1. Other times I might have 20 packages (in that case I'd like it to return 20).

My JObject looks like this:

JObject o = JObject.Parse(myJsonString);

Any ideas? Thanks for any help.

Upvotes: 16

Views: 60218

Answers (6)

Andriy Tolstoy
Andriy Tolstoy

Reputation: 6100

Using deserialization to a dictionary type:

JsonConvert.DeserializeObject<IDictionary>(myJsonString).Count

or

JsonConvert.DeserializeObject<IDictionary<string, object>>(myJsonString).Count

Upvotes: 0

DerpyCoder
DerpyCoder

Reputation: 135

 string json= "{
"package1": {
"type": "envelope",
"quantity": 1,
"length": 6,
"width": 1,
"height": 4
 },
 "package2": {
 "type": "box",
 "quantity": 2,
 "length": 9,
 "width": 9,
 "height": 9
 }
 }"; 

 dynamic stuff;
 int count;
 stuff = JsonConvert.DeserializeObject(json);
 foreach(JProperty s in stuff){

  count++;
  }

  Console.WriteLine(count.ToString());

If the Count property does not work out for you, try this instead. Ensure that your C# version is 4.0 or higher, as the dynamic keyword was added at that time.

Upvotes: 0

Cinchoo
Cinchoo

Reputation: 6332

With Cinchoo ETL - an open source library, you can do the node count easily with less memory overhead, as it is using streaming approach to parse the input. Hence it can handle large file as well.

string json = @"{
""package1"": {
""type"": ""envelope"",
""quantity"": 1,
""length"": 6,
""width"": 1,
""height"": 4
},
""package2"": {
""type"": ""box"",
""quantity"": 2,
""length"": 9,
""width"": 9,
""height"": 9
}
}";

using (var p = ChoJSONReader.LoadText(json).WithJSONPath("$.*"))
{
    Console.WriteLine(p.Count());
}

Hope it helps.

Upvotes: 0

Thymine
Thymine

Reputation: 9205

Recursive version (count all properties with primitive values)

Came across this question trying to google for a recursive count of JObject values, didn't find many other questions, so figured I'd add what I came up with to this question as well

int CountJTokenProperties(JToken token)
{
    var sum = 0;

    if (token.Type == JTokenType.Object)
    {
        foreach (var child in token.Value<JObject>())
        {
            sum += CountJTokenProperties(child.Value);
        }
    }
    else if (token.Type == JTokenType.Array)
    {
        foreach (var child in token.Value<JArray>())
        {
            sum += CountJTokenProperties(child);
        }
    }
    else
    {
        sum += 1;
    }

    return sum;
}

There might be a better alternative to .Value<JObject>() and .Value<JArray>(), but this seems to be working.

And specifically I wanted this for a nunit test that had variable sample data, and wanted to make sure it deserialized correctly. Decided that an easy way to check would be how many non-default values there were on the C# object, and JsonConvert has that ability:

public int CountNonDefaultProperties(object obj)
{
    // Let JsonConvert do the work of stripping out default values
    var serialized = JsonConvert.SerializeObject(obj, new JsonSerializerSettings
    {
        DefaultValueHandling = DefaultValueHandling.Ignore
    });

    // Recurse into the json structure, which is much simpler than C# Object structure
    var jObj = JObject.Parse(serialized);

    return CountJTokenProperties(jObj);
}

Note that DefaultValueHandling.Ignore keeps default values that are part of arrays, so if you wanted that feature you'd need to count the array items in a different way or something, this activity is left to the reader

https://dotnetfiddle.net/XIZCvh

Upvotes: 0

L.B
L.B

Reputation: 116168

JObject jObj = (JObject)JsonConvert.DeserializeObject(myJsonString);
int count = jObj.Count;

BONUS:

dynamic jObj = JsonConvert.DeserializeObject(myJsonString);

foreach (var package in jObj)
{
    Console.WriteLine("{0} {1}", package.First.type, package.First.quantity);
}

Upvotes: 32

Har
Har

Reputation: 5004

in JQuery $.ajax you will receive an array, traverse through the elements and get the sum.

Upvotes: -2

Related Questions