Search code examples
c#json.netexpandoobject

Convert JSON string to dynamic, update property, convert back to JSON


When I need to call an API to update a complex object, what I want to do is:

  1. GET - Read down the object (as a JSON string).
  2. Convert to a dynamic object.
  3. Write the new value(s) to the properties I'm updating.
  4. Convert to a JSON string.
  5. POST - Write the updated object to the API.

I wrote the following code and it doesn't work. I'm struggling because I'm not sure exactly what/where the issue is as I don't understand exactly what either a JSON object or dynamic object is. (I sort-of do, but clearly not that well.)

var client = CreateRequest($"https://api.securevan.com/v4/events/{EventId}", out var requestEvent);
var responseEvent = await client.GetAsync(requestEvent);

dynamic eventJson = JsonConvert.DeserializeObject<dynamic>(responseEvent.Content);
eventJson.description = "API Test Event Updated";
string jsonStr = JsonConvert.SerializeObject(eventJson, Formatting.Indented);

request.AddJsonBody(jsonStr, false);

var response = await client.PutAsync(request);

The above blows up as a BadRequest. So somewhere in the converting back and forth I'm not doing something right. What do I have wrong?


Solution

  • You can use classes in System.Text.Json and System.Text.Json.Nodes to handle such dynamic serialization and deserialization. Due to the dynamic nature of data, we better use raw JSON structures. You can see below for example:

    using System.Text;
    using System.Text.Json;
    using System.Text.Json.Nodes;
    
    var json = @"{""description"": ""hello world""}";
    
    var jsonObject = JsonObject.Parse(json).AsObject();
    jsonObject["description"] = "updated";
    
    using var memoryStream = new MemoryStream();
    using var writer = new Utf8JsonWriter(memoryStream);
    
    jsonObject.WriteTo(writer);
    writer.Flush();
    
    var serialized = Encoding.UTF8.GetString(memoryStream.ToArray());
    
    Console.WriteLine(serialized);
    

    It will give following output:

    {"description":"updated"}