Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determine if JToken is leaf

Tags:

json

c#

json.net

I'm trying to dynamically find the names of leaf nodes of a JSON object whose structure isn't known in advance. First, I'm parsing the string into a list of JTokens, like this:

        string req = @"{'creationRequestId':'A',
                        'value':{
                            'amount':1.0,
                            'currencyCode':'USD'
                        }
                        }";
        var tokens = JToken.Parse(req);

Then I'd like to identify which are leaves. In the above example, 'creationRequestId':'A', 'amount':1.0, and 'currencyCode':'USD' are the leaves, and the names are creationRequestId, amount, and currencyCode.

Attempt that works, but is slightly ugly

The below example recursively traverses the JSON tree and prints the leaf names:

    public static void PrintLeafNames(IEnumerable<JToken> tokens)
    {
        foreach (var token in tokens)
        {
            bool isLeaf = token.Children().Count() == 1 && !token.Children().First().Children().Any();
            if (token.Type == JTokenType.Property && isLeaf)
            {
                Console.WriteLine(((JProperty)token).Name);
            }

            if (token.Children().Any())
                PrintLeafNames(token.Children<JToken>());
        }
    }

This works, printing:

creationRequestId
amount
currencyCode

However, I'm wondering if there's a less ugly expression for determining whether a JToken is a leaf:

bool isLeaf = token.Children().Count() == 1 && !token.Children().First().Children().Any();

Incidentally, this is a one-liner in XML.

like image 777
Peter Richter Avatar asked Oct 28 '25 07:10

Peter Richter


1 Answers

It looks like you've defined a leaf as any JProperty whose value does not have any child values. You can use the HasValues property on the JToken to help make this determination:

public static void PrintLeafNames(IEnumerable<JToken> tokens)
{
    foreach (var token in tokens)
    {
        if (token.Type == JTokenType.Property)
        {
            JProperty prop = (JProperty)token;
            if (!prop.Value.HasValues)
                Console.WriteLine(prop.Name);
        }
        if (token.HasValues)
            PrintLeafNames(token.Children());
    }
}

Fiddle: https://dotnetfiddle.net/e216YS

like image 123
Brian Rogers Avatar answered Oct 29 '25 21:10

Brian Rogers



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!