17

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.

6 Answers 6

33
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);
}
Sign up to request clarification or add additional context in comments.

4 Comments

Thank you so much! This has been driving me crazy for days. I'll mark it correct in 4 minutes:)
Ha I accepted it before I read the recommended 24-48 hour waiting period. I'm new so I'm still learning. Anyway, thanks again for your help.
@BrentBarbata see the bonus if you can use dynamic
The second way works even better for what I'm ultimately trying to do. Thank you a million times!
0

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

Comments

0

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.

Comments

0
 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.

Comments

0

Using deserialization to a dictionary type:

JsonConvert.DeserializeObject<IDictionary>(myJsonString).Count

or

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

Comments

-2

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

1 Comment

Thanks a lot for the response, but I'm trying to figure out how to do this with Json.NET in C#.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.