RShome
RShome

Reputation: 537

How to remove a key value pair within a nested json structure in C#

I have the following json

{       
 "audit_date": "2020-05-13T11:27:10.3187798Z",
 "client_uuid": "2fd77dd8-ed76-4bba-b0e1-5cda454c8d6e",
 "audit_entry": {
    "where_uri": "test.com/dataservice/apps/171f0841-825b-4964-8f8c-0869650f14a6",
    "why_uri": "test.com/dataservice/reference/reasons_for_change/61acc173-7168-4ae5-9f04- afa228941f8b",
    "who_uri": "test.com/securityservice/users/4977dae1-a307-425f-980c-53413fef1b0f",
    "when_audited": "2018-11-13T20:20:39+00:00",
    "what_uri": "test.com/dataservice/study_subjects/1bc67a71-8549-4ab8-9dd9-e44238198860",
    "what_changed": [
        {
            "attribute_name": "birth_year",
            "attribute_value": "1969",
        "attribute_change": "1970"
        },
        {
            "attribute_name": "subject_reference",
            "attribute_value": "TEST-WOO3444",
            "attribute_change": null
        }
      ]
     }
    }

And I want to remove the second attribute_change key value pair to be as follows

{       
"audit_date": "2020-05-13T11:27:10.3187798Z",
"client_uuid": "2fd77dd8-ed76-4bba-b0e1-5cda454c8d6e",
"audit_entry": {
    "where_uri": "test.com/dataservice/apps/171f0841-825b-4964-8f8c-0869650f14a6",
    "why_uri": "test.com/dataservice/reference/reasons_for_change/61acc173-7168-4ae5-9f04- afa228941f8b",
    "who_uri": "test.com/securityservice/users/4977dae1-a307-425f-980c-53413fef1b0f",
    "when_audited": "2018-11-13T20:20:39+00:00",
    "what_uri": "test.com/dataservice/study_subjects/1bc67a71-8549-4ab8-9dd9-e44238198860",
    "what_changed": [
        {
            "attribute_name": "birth_year",
            "attribute_value": "1969",
        "attribute_change": "1970"
        },
        {
            "attribute_name": "subject_reference",
            "attribute_value": "TEST-WOO3444",
            
        }
      ]
     }
    }

I have tried the following code

        JObject jObject = JObject.Parse(jsonText);
        JObject jObj = (JObject)jObject.SelectToken("audit_entry");

        //remove second attribute changed token
        jObj.Property("what_changed")("attribute_change")[1].Remove();

        string json = jObj.ToString(Formatting.None);

I know the syntax is wrong for jObj.Property but after a few hours of googling I cannot find the answer. Any help much appreciated.

Upvotes: 0

Views: 3346

Answers (3)

Guru Stron
Guru Stron

Reputation: 143328

You can remove a property from JObject by calling Remove method with corresponding property name. For example:

JObject jObject = JObject.Parse(jsonText);

// find required object, there are other options
// for example (JObject)jObject["audit_entry"]["what_changed"][1]
var nested = (JObject)jObject.SelectToken("$.audit_entry.what_changed[1]"); 

//remove attribute changed token
nested.Remove("attribute_change");
string json = jObject.ToString(Formatting.None); // attribute_change is removed from jObject

If you want to remove all properties with such name and null for value you can do next:

        var toRemove = jObject.Descendants()
            .OfType<JProperty>()
            .Where(prop => prop.Name == "attribute_change" && prop.Value.Type == JTokenType.Null)
            .ToList();
        foreach (var prop in toRemove)
        {
            prop.Remove();
        }

Upvotes: 2

Pavel Anikhouski
Pavel Anikhouski

Reputation: 23298

Since what_changed is an array, you should cast to JArray to be able to access its elements and remove attribute_change token

var jObject = JObject.Parse(jsonText);

if (jObject["audit_entry"]?["what_changed"] is JArray array)
    if (array[1] is JObject attribute)
        attribute.Remove("attribute_change");

Console.WriteLine(jObject);

Upvotes: 1

user10944925
user10944925

Reputation:

Search for the beginning attribute name and its end. Then concatenate the json string before/after into a new string. Perhaps a hack, but it will keep you coding until you find a more elegant solution.

Upvotes: 1

Related Questions