How to Deserialize JSON that Contains an Embedded JSON String in C#
By FoxLearn 3/19/2025 7:41:13 AM 40
The outer box has labels and information (the metadata), while the inner gift has specific details about the item it represents.
While using an embedded JSON string is uncommon, there are situations where it may be necessary. If possible, consider deserializing to a derived type, using JsonDocument
to parse the JSON string, or employing JsonExtensionData
to catch properties that aren't part of the model. If you find that using an embedded JSON string is unavoidable, continue reading for an example.
Creating the JSON Package
Here’s an example of a JSON package, which contains an embedded JSON string (highlighted):
{ "PackageType": "Order", "Details": "{\"OrderId\":\"12345\",\"Customer\":\"John Doe\",\"Total\":99.99}" }
This JSON package contains routing information (PackageType
) and an embedded JSON string (Details
). The embedded JSON string is escaped (encoded), which is why it appears as a single string within the JSON package.
This JSON was generated by serializing the following class:
public class JsonPackage { public string PackageType { get; set; } public string Details { get; set; } }
The sender creates this JSON package by first serializing the order details, then wrapping it inside the JSON package:
var jsonPackage = new JsonPackage() { PackageType = "Order", Details = JsonSerializer.Serialize(new Order() { OrderId = "12345", Customer = "John Doe", Total = 99.99 }) }; var jsonToSend = JsonSerializer.Serialize(jsonPackage, options);
Routing the JSON Package
The sender sends the JSON package to a service. The service has a route map, which helps determine how to handle messages based on the PackageType
field. Although routing can be set up in many ways, this article focuses on how to deserialize the JSON package.
To route the package correctly, the service first deserializes the JSON package to extract the routing information. Then it routes the embedded JSON string to the appropriate handler:
public static void Route(string json) { var jsonPackage = JsonSerializer.Deserialize<JsonPackage>(json); var handler = routeMap[jsonPackage.PackageType]; handler.Handle(jsonPackage.Details); } private static readonly Dictionary<string, IMessageHandler> routeMap = new Dictionary<string, IMessageHandler>();
This is an example of the plugin pattern, where plugins implement the IMessageHandler
interface. The routing logic uses the value in the JSON package (PackageType
) to look up the correct handler in the dictionary.
public interface IMessageHandler { void Handle(string json); }
Processing the Embedded JSON Data
Once the embedded JSON string is routed to the correct handler, it is deserialized into the appropriate object for further processing. In this example, the handler deserializes the embedded JSON into an Order
object using a class called OrderProcessor
:
public class OrderProcessor : IMessageHandler { public void Handle(string orderJson) { var order = JsonSerializer.Deserialize<Order>(orderJson); Console.WriteLine($"Processing Order {order.OrderId} for {order.Customer}"); } } public class Order { public string OrderId { get; set; } public string Customer { get; set; } public decimal Total { get; set; } }
The OrderProcessor
class processes the embedded Order
JSON by deserializing it and then performing any necessary actions (such as processing payment or updating inventory).
- Primitive types in C#
- How to set permissions for a directory in C#
- How to Convert Int to Byte Array in C#
- How to Convert string list to int list in C#
- How to convert timestamp to date in C#
- How to Get all files in a folder in C#
- How to use Channel as an async queue in C#
- Case sensitivity in JSON deserialization