3

I am trying to remove some properties which are dynamic input from JObject(converted json to JObject). i can do this on parent elements but not the nested child elements. INPUT

 {
  "id": 1,
  "name": "something",
  "marks": [
    {
      "pid": 1000,
      "sub": "AAA",
      "rank": 2
    },
    {
      "pid": 1001,
      "sub": "BBB",
      "rank": 10
    }
  ]
}

Now i wand to remove the id from parent and pid from each marks property in json. This list is dynamic and may grow in future. data is above provided is an example but the original list(marks in example) contains more than 20 properties.

CODE TRIED (which is deleting only id property from the parent)

string[] props = new string[] { "id", "pid" };
JObject jObject = JsonConvert.DeserializeObject<JObject>(str.ToLower());
if (jObject != null)
{
    jObject.Properties()
           .Where(attr => props.Contains(attr.Name))
           .ToList()
           .ForEach(attr => attr.Remove());
}
1
  • You could create a model that matches your JSON object and exclude the properties you don't want serialized. For this example, you might try mark.pid. Commented May 4, 2020 at 12:09

2 Answers 2

4

You can create a function and call it recursively if the nested values are JObject or JArray, like the following code:

1 - Create the main function RemoveIds:

public static void RemoveIds(JObject jObject, string[] props)
{
    List<JProperty> jProperties = jObject.Properties().ToList();

    for (int i = 0; i < jProperties.Count; i++)
    {
        JProperty jProperty = jProperties[i];
        if (jProperty.Value.Type == JTokenType.Array)
        {
            RemoveFromArray((JArray)jProperty.Value, props);
        }
        else if (jProperty.Value.Type == JTokenType.Object)
        {
            RemoveIds((JObject)jProperty.Value, props);
        }
        else if (props.Contains(jProperty.Name))
        {
            jProperty.Remove();
        }
    }
}

2 - Create simple method RemoveFromArray that call the main function inside a loop:

private static void RemoveFromArray(JArray jArray, string[] props)
{
    foreach(JObject jObject in jArray)
    {
        RemoveIds(jObject, props);
    }
}

3 - Call main function in the code like :

JObject jObject = JsonConvert.DeserializeObject<JObject>(json.ToLower());
if (jObject != null)
{
    RemoveIds(jObject, new string[] { "id", "pid" });

    Console.WriteLine(jObject);
}

4 - Result:

{
  "name": "something",
  "marks": [
    {
      "sub": "aaa",
      "rank": 2
    },
    {
      "sub": "bbb",
      "rank": 10
    }
  ]
}

I hope you find this helpful.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks looks more generic.. and can be used for any json structure.
0

The answer from @Mohammed Sajid was exactly what I was looking for! However, I found that if the property I was wanting to remove was itself an object, it did not get removed. I switched the order of the if/else tests to put the test for removing first which solved my problem. On top of this, since I'm only ever searching for a single property to remove in a large and complex object, I also added an optional findOnce parameter which, if set to true will quit out of the iteration and recursion loops as soon as the property has been removed, thereby saving a few runs around the loop.

public static bool RemoveIds(JObject jObject, string props, in bool findOnce = true)
{
    List<JProperty> jProperties = jObject.Properties().ToList();

    bool Found = false;

    for (int i = 0; i < jProperties.Count; i++)
    {
        if (findOnce && Found) break;

        JProperty jProperty = jProperties[i];
        if (props == jProperty.Name)
        {
            jProperty.Remove();
            Found = true;
        }
        else if (jProperty.Value.Type == JTokenType.Array)
        {
            Found = RemoveFromArray((JArray)jProperty.Value, props, findOnce);
        }
        else if (jProperty.Value.Type == JTokenType.Object)
        {
            Found = RemoveIds((JObject)jProperty.Value, props, findOnce);
        }
    }
    return Found;
}
private static bool RemoveFromArray(JArray jArray, string props, in bool findOnce = true )
{
    bool Found = false;
    foreach (JObject jObject in jArray)
    {
        Found = RemoveIds(jObject, props, findOnce);
        if( findOnce && Found ) return true;
    }
    return Found;
}

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.