skip to Main Content

I have a json file as follows

{
    "desc": "my desc",
    "lang": "en",
    "issue": {
        "date": "2024-09-01",
        "title": "Empowering Razor Club"
    },
    "stars": [
        {
            "id": 1,
            "value": 5
        },
        {
            "id": 2,
            "value": 4
        }
    ]
}

This json structure is fixed and won’t change but the value can change. I want create a method to update particular property value and save back to file.

Using Newtonsoft.Json SelectToken is easy by placing dot (.) for nested properties or even arrays such as "issue.title" or "stars[0].value". When it comes to System.Text.Json I find it harder.

private void UpdateJsonValue(string path, object value)
{
    var json = "the above sample"
    var node = JsonNode.Parse(json);
    node[path] = JsonValue.Create(value); //error's here
    
    json = node.ToJsonString();
    //save json to file
}

UpdateJsonValue("issue.title", "Hello World");
UpdateJsonValue("stars[[1].value", 5);

So, how to get JsonNode with nested properties?

2

Answers


  1. Since
    a) the structure is fixed
    b) the value you are trying to change is particular and not generic,

    deserialize into a class and serialize back into a file. This is how:

    1. Make a C# class for your structure. You can get this result by copying the json structure and in visual studio, navigating to the following menu: EDIT > PASTE SPECIAL > PASTE JSON AS CLASSES
        public class Rootobject
        {
            public string desc { get; set; }
            public string lang { get; set; }
            public Issue issue { get; set; }
            public Star[] stars { get; set; }
        }
        
        public class Issue
        {
            public string date { get; set; }
            public string title { get; set; }
        }
        
        public class Star
        {
            public int id { get; set; }
            public int value { get; set; }
        }
    
    1. Deserialize json into the C# class. Ideally, make a separate function for this that accepts filepath, with a try/catch in case the json structure doesn’t match the class anymore.
        var filepath = "C:/file.json";
        Rootobject data;
        
        if (File.Exists(filepath))
        {
            string result = string.Empty;
            using (StreamReader r = new StreamReader(filepath))
            {
                var json = r.ReadToEnd();
                data = JsonSerializer.Deserialize<Rootobject>(json);
            }
        }
        else
        {
            return null;
        }
    
    1. Look up the value. Do a check for null and such yourself, to avoid null reference errors later on.
        var star = data.stars.FirstOrDefault(s => s.id == 1);
    
    1. Change the value
        star.value = 5;
    
    1. Serialize back into json. Make this into a proper function too, with the necessary checks and try/catch
        var newjson = JsonSerializer.Serialize(data);
        File.WriteAllText(filepath, newjson);
    
    Login or Signup to reply.
  2. Consider the following method:

    void UpdateJsonValue(object value, params object[] path)
    {
        var json = File.ReadAllText("test.json");
        var node = JsonNode.Parse(json);
    
        var temp = node;
        foreach (var item in path)
        {
            if (item is string propertyName)
                temp = temp[propertyName];
    
            if (item is int index)
                temp = temp[index];
        }
        temp.ReplaceWith(value.ToString());
    
        Console.WriteLine(node);    
    }
    

    Use it in the following way:

    UpdateJsonValue("Hello World", "issue", "title");
    UpdateJsonValue(555, "stars", 1, "value");
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search