0

I have an array like this coming from API response and I want to filter by nested property products to returns product with only id 11

  "assets": [
    {
      "name": "abc",
      "products": [
        {
          "id": "11",
          "status": true
        },
        {
          "id": "14",
          "status": null
        }
      ]
    },
    {
      "name": "xyz",
      "products": [
        {
          "id": "11",
          "status": true
        },
        {
          "id": "28",
          "status": null
        }
      ]
    },
    {
      "name": "123",
      "products": [
        {
          "id": "48",
          "status": null
        }
      ]
    },
    {
      "name": "456",
      "products": [
        {
          "id": "11",
          "status": true
        }
      ]
    }
  ]

the resulting output should look like this,

  "assets": [
    {
      "name": "abc",
      "products": [
        {
          "id": "11",
          "status": true
        }
      ]
    },
    {
      "name": "xyz",
      "products": [
        {
          "id": "11",
          "status": true
        }
      ]
    },
    {
      "name": "123",
      "products": []
    },
    {
      "name": "456",
      "products": [
        {
          "id": "11",
          "status": true
        }
      ]
    }
  ]

I'm trying to return filter output with the C# LINQ method. but, getting an error when filtering a nested array with the following method

"Cannot convert lambda expression to intended delegate type because some of the return types in the block are not implicitly convertible to the delegate return type"

assets.Select(asset => asset.products.Where(product => product.id == "11")).ToArray();
3
  • 3
    What error are you getting? Commented Jun 8, 2020 at 23:58
  • I'm getting this error "Cannot convert lambda expression to intended delegate type because some of the return types in the block are not implicitly convertible to the delegate return type" Commented Jun 9, 2020 at 0:01
  • You need to put the error in your question, not in a comment. Commented Jun 10, 2020 at 17:42

3 Answers 3

1

You can just remove all items from every products array, whose id doesn't equal 11. Parse JSON to JObject, iterate over assets array, find products with id different from 11 and remove them form original array

var json = JObject.Parse(jsonString);

foreach (var asset in json["assets"])
{
    var productsArray = asset["products"] as JArray;
    if (productsArray == null)
        continue;

    var productsToRemove = productsArray
        .Where(o => o?["id"]?.Value<int>() != 11)
        .ToList();

    foreach (var product in productsToRemove) 
        productsArray.Remove(product);
}

Console.WriteLine(json);
Sign up to request clarification or add additional context in comments.

1 Comment

@SanjayV Does it answer your question, do you need more details or information?
1

Instead of Select and Applying a, Where try to remove the Products that you do not want.

Following is a sample code.

class Program
    {
        static void Main(string[] args)
        {

            var json = @"
                {
                    'assets': [
                    {
                    'name': 'abc',
                    'products': [
                        {
                        'id': '11',
                        'status': true
                        },
                        {
                        'id': '14',
                        'status': null
                        }
                    ]
                    },
                    {
                    'name': 'xyz',
                    'products': [
                        {
                        'id': '11',
                        'status': true
                        },
                        {
                        'id': '28',
                        'status': null
                        }
                    ]
                    },
                    {
                    'name': '123',
                    'products': [
                        {
                        'id': '48',
                        'status': null
                        }
                    ]
                    },
                    {
                    'name': '456',
                    'products': [
                        {
                        'id': '11',
                        'status': true
                        }
                    ]
                    }
                ]}";

            var root = JsonConvert.DeserializeObject<Root>(json);
            var assets = root.Assets;
            assets.ForEach(a =>
            {
                a.Products.RemoveAll(p => p.Id != 11);
            });
        }
    }

    public partial class Root
    {
        [JsonProperty("assets")]
        public List<Asset> Assets { get; set; }
    }

    public partial class Asset
    {
        [JsonProperty("name")]
        public string Name { get; set; }

        [JsonProperty("products")]
        public List<Product> Products { get; set; }
    }

    public partial class Product
    {
        [JsonProperty("id")]
        public long Id { get; set; }

        [JsonProperty("status")]
        public bool? Status { get; set; }
    }

Comments

1

To filter the list, you will need to create a new list with products whose ID == YourId. Following linq query does the necessary steps to create the list you want.

  1. Filter out any assets that dont have any product with ID == 11. This is necessary to skip nulls in the new list that will be generated (Where statement)
  2. Create a collection / list of new assets that only have the products whose ID == 11 (Select statement)
var list = assets.Where(x => x.Products.Where(y => y.Id.Equals("11")).Count() > 0)
                    .Select(asset => { 
                        return new Asset() { 
                            Name = asset.Name, 
                            Products = asset.Products.Where(x => x.Id == "11").ToList() 
                            }; 
                    }).ToList();

// Create the RootObject that holds a list of all the arrays if you want.
Rootobject newAssetCollection = new Rootobject() { Assets = list };

Below is the Json that was printed

Console.WriteLine(JsonConvert.SerializeObject(newAssetCollection, Formatting.Indented));

{
  "assets": [
    {
      "name": "abc",
      "products": [
        {
          "id": "11",
          "status": true
        }
      ]
    },
    {
      "name": "xyz",
      "products": [
        {
          "id": "11",
          "status": true
        }
      ]
    },
    {
      "name": "456",
      "products": [
        {
          "id": "11",
          "status": true
        }
      ]
    }
  ]
}

Comments

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.