Combining multiple untyped JSONs
Usually, before manipulating JSON inputs, you first deserialize them into strongly typed objects that match their structure. However, that might not always be possible. Recently, I had to combine multiple JSON inputs into a single JSON array, without any knowledge of the input JSON structure.
Trying to deserialize such JSON inputs into strongly typed objects would result in losing any properties that weren't expected. This wasn't an option.
I could resort to basic string manipulation, completely ignoring the fact that I was dealing with JSON:
var jsonArray = $"[{json1},{json2}]";
This would be the most performant approach. But in the worst case, it could result in an invalid JSON array if any of the inputs weren't valid JSON values.
Instead, I decided to take advantage of the JsonElement
type from the JSON document object model. This will preserve the complete JSON object structure, even if you don't know the exact properties it contains. The resulting objects can then be collected in an array and deserialized back to JSON:
public static string ToArray(params string[] jsons)
{
return JsonSerializer.Serialize(
jsons.Select(json => JsonSerializer.Deserialize<JsonElement>(json)));
}
With this approach, I could be sure that the resulting string will be a valid JSON array, no matter what the input would be like.
In a Mastodon discussion, Matthew Adams and Greg Dennis suggested an even better approach, bypassing the JsonSerializer
class as the intermediary and using JsonNode
directly to do the deserialization and serialization:
public static string ToArray(params string[] jsons)
{
return new JsonArray(
jsons.Select(json => JsonNode.Parse(json)).ToArray()
).ToJsonString();
}
You can find both versions of the code as individual commits in my GitHub repository. To validate the resulting JSON in a test, I take advantage of FluentAssertions.Json. I wrote in more detail about this NuGet package in a previous blog post.
When dealing with JSON, there is usually no need to use the JsonElement
type. However, its ability to represent any JSON value can be beneficial when you don't have full information about that value. I only used it to combine multiple values into an array, but I could also inspect a value before deciding how to further process it.