0

I deserialize a JSON from a third-party provider into an object and want to query that object looking for a value in a specific property.

My problem is that the object has a property (Parts) whose value is a list with the same type.

public class RulePartModel
{
    public string isExistsUnder { get; set; }
    public int State { get; set; }       
    public string Value { get; set; }
    public List<RulePartModel> Parts { get; set; }
}

How can I query this object to find a specific Value when the Parts property can have 6 or 7 levels?

Here is a sample of the JSON I receive as an answer:

{
  "isExistsUnder": null,
  "State": "",
  "Value": "CustomElements",
  "Parts": [
    {
      "isExistsUnder": null,
      "State": 0,      
      "Value": "Rule 73",
      "Parts": [
        {
          "isExistsUnder": null,
          "State": "",
          "Value": "For variable initializations",
          "Parts": [
            {
              "isExistsUnder": null, 
              "State": "",             
              "Value": "cupis",
              "Parts": [
                {
                  "isExistsUnder": null,
                  "State":"",
                  "Value": "randomText1",
                  "Parts": []
                },
                {
                  "isExistsUnder": null,
                  "State":"",
                  "Value": "randomText2",
                  "Parts": []
                },
                {
                  "isExistsUnder": null,
                  "State":"",
                  "Value": "randomText3",
                  "Parts": []
                }
              ]
            }
        }
    }
}
2
  • Does Parts only ever have a single element at the top, or can there be multiple sub-parts on the same level? Commented Aug 22, 2018 at 13:50
  • There can be multiple sub-parts at the same level. I update the json example to show that. Commented Aug 23, 2018 at 6:50

1 Answer 1

2

try this:

        static void Main(string[] args)
    {
        var testobj = new RulePartModel();
        var results = FindParts(testobj, q => q.Value == "123");
        // results =>>> all objects with your condition
    }
    static IEnumerable<RulePartModel> FindParts(RulePartModel obj, Func<RulePartModel, bool> predicate)
    {
        if (predicate.Invoke(obj))
            yield return obj;
        foreach (var item in obj.Parts)
            foreach (var res in FindParts(item, predicate))
                yield return res;
    }

or use @Parrish suggestion for non-recursive function:

        static IEnumerable<RulePartModel> FindParts(RulePartModel obj)
    {
        var stack = new Stack<RulePartModel>();
        stack.Push(obj);
        while (stack.Count > 0)
        {
            var current = stack.Pop();
            yield return current;
            foreach (var item in current.Parts)
                stack.Push(item);
        }
    }

usage example :

var results = FindParts(testobj).Where(q => q.Value == "123");
Sign up to request clarification or add additional context in comments.

4 Comments

To add to this answer, you can do this non-recursively also. See Eric Lipperts answer here: stackoverflow.com/a/20335369/1316856
its true but he said 6-7 levels ... so this answer works for him i think
OP never indicated how may parts can exist per level, so the example could be much simpler.
@AntonínLejsek. you right about using current object in second example i forgot to edit that loop. thanks

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.