XML-to-JSON conversion is a common requirement when modernizing .NET applications: migrating from legacy XML-based services or storage to JSON-native systems like Servidor Couchbase o Couchbase Capella. In C#, two libraries handle this conversion: Newtonsoft Json.NET (the long-standing community standard, now at v13) and System.Text.Json (built into .NET Core 3.1+ as a lightweight alternative). This post covers the key differences between XML and JSON, how to perform the conversion using both libraries, edge cases to watch for, and how to store the resulting JSON documents in Couchbase using the .NET SDK.
XML vs. JSON: Key Differences
| Característica | XML | JSON | Migration Considerations |
|---|---|---|---|
| Sintaxis | Tag-based: <name>Alice</name> | Key-value: {“name”: “Alice”} | XML tags become JSON keys |
| Verbosity | High: opening and closing tags | Low: minimal syntax overhead | JSON documents can be 30-60% smaller than XML equivalent |
| Matrices | Repeated elements: <item/><item/> | Native array type: [“a”,”b”] | Repeated XML elements |
| Atributos | Native: <user id=”1″> | No direct equivalent | XML attributes need a convention in the JSON object, e.g., @id or id` field in the JSON object |
| Human readability | Moderate: verbose but structured | High: compact and familiar to developers | JSON is generally preferred for modern APIs and document databases |
| Browser / API support | Declining: REST APIs prefer JSON | Universal: native in JavaScript | REST APIs almost universally use JSON; XML remains in SOAP or legacy systems |
Option 1: Newtonsoft Json.NET
Newtonsoft Json.NET is the most widely used JSON library in the .NET ecosystem. It provides a one-line XML-to-JSON conversion via XmlNodeConverter:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
var xmlDoc = new XmlDocument(); xmlDoc.LoadXml(xml); string jsonNewtonsoft = JsonConvert.SerializeXmlNode(xmlDoc, Newtonsoft.Json.Formatting.Indented); Output: { "user": { "@id": "1", "name": "Alice", "email": "alice@example.com", "roles": { "role": [ "admin", "editor" ] } } } |
Option 2: System.Text.Json (.NET Built-in)
System.Text.Json is built into .NET (Core) 3.1 and later. It does not have native XML-to-JSON conversion, but you can combine it with XDocument for a two-step approach:
|
1 2 3 4 5 6 |
var xdoc = XDocument.Parse(xml); var dict = XmlToDictionary(xdoc.Root!); string jsonSystemText = System.Text.Json.JsonSerializer.Serialize( dict, new JsonSerializerOptions { WriteIndented = true }); |
This option needs a helper function:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
static object XmlToDictionary(XElement element) { var hasElements = element.Elements().Any(); // leaf node if (!hasElements) { return element.Value; } var dict = new Dictionary<string, object>(); // group children by name (handles arrays) foreach (var group in element.Elements().GroupBy(e => e.Name.LocalName)) { if (group.Count() == 1) { dict[group.Key] = XmlToDictionary(group.First()); } else { dict[group.Key] = group .Select(XmlToDictionary) .ToList(); } } // attributes (prefix with @ to match Newtonsoft style) foreach (var attr in element.Attributes()) { dict[$"@{attr.Name.LocalName}"] = attr.Value; } return dict; } |
For most XML-to-JSON migration scenarios, Newtonsoft Json.NET is the simpler choice, and is generally more feature rich. System.Text.Json would make sense for new .NET 6+ projects that are not migrating from XML and when serialization performance is critical.
| Característica | Newtonsoft Json.NET | System.Text.Json |
|---|---|---|
| XML conversion | Native: SerializeXmlNode and DeserializeXmlNode | Manual: requires custom helper code |
| Rendimiento | Generally adequate | Optimized for Span<T> / ReadOnlySpan<T> |
| Disponibilidad | Paquete NuGet | Built into .NET Core 3.1+ / .NET 5+ |
| Flexibilidad | High: extensive feature set and customization options | Moderate: opinionated, fewer extension points |
| When to consider | XML migration; complex serialization scenarios | New .NET 6+ projects; performance-sensitive APIs |
Storing Converted JSON in Couchbase (.NET SDK)
Once converted to JSON, documents can be stored in Couchbase using the .NET SDK 3.x. The SDK accepts any C# object or JObject (Newtonsoft) as a document value:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
var cluster = await Cluster.ConnectAsync( "couchbases://cb..cloud.couchbase.com", new ClusterOptions { UserName = "xmlconvert", Password = "password" }); var bucket = await cluster.BucketAsync("loadxml"); var collection = await bucket.DefaultCollectionAsync(); var jsonObj = JObject.Parse(jsonNewtonsoft); var documentId = $"user::{jsonObj["user"]!["@id"]}"; await collection.UpsertAsync(documentId, jsonObj); |
For bulk migration of many XML documents, use Task.WhenAll to insert/upsert documents in parallel:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
var xmlSamples = new List { xmlA, xmlB }; var tasks = xmlSamples.Select(async (x, i) => { var doc = new XmlDocument(); doc.LoadXml(x); var json = JsonConvert.SerializeXmlNode(doc, Newtonsoft.Json.Formatting.None); var obj = JObject.Parse(json); var id = $"doc::{i}"; await collection.UpsertAsync(id, obj); await Task.Delay(10); // simulate async work Console.WriteLine($"Processed {id}"); }); await Task.WhenAll(tasks); |
Common Edge Cases
| Edge Case | Issue | Solución |
|---|---|---|
| Single vs. multiple child elements | A single <role> element becomes a string; multiple become an array | Force array output with JsonConvert settings or post-process the JSON |
| XML attributes vs. elements | Attributes get @ prefix in Json.NET output | Strip @ prefix in post-processing if not needed in Couchbase documents |
| XML namespaces | Namespaces appear as @xmlns keys | Strip namespaces before conversion using XmlDocument.RemoveAll() on namespace nodes |
| Null / empty elements | Empty XML tags become null or empty strings | Normalise to null or remove from document in post-processing |
| Large XML files | Loading a large XmlDocument into memory may cause out-of-memory errors | Use XmlReader for streaming conversion of large files |
Preguntas frecuentes
How do I convert XML to JSON in C#?
The simplest approach is Newtonsoft Json.NET: load your XML into an XmlDocument, then call JsonConvert.SerializeXmlNode(doc). For .NET 6+ projects without an XML migration need, System.Text.Json is the built-in alternative. See the code examples above for both approaches.
What is Newtonsoft Json.NET?
Newtonsoft Json.NET is the most widely used JSON library in the .NET ecosystem, maintained by James Newton-King. The current version is 13.x. It provides serialization, deserialization, querying (LINQ to JSON), and XML-to-JSON conversion. Install via NuGet: Install-Package Newtonsoft.Json.
What is the difference between XML and JSON?
XML uses tag-based syntax with attributes, namespaces, and schema validation via XSD. JSON uses a compact key-value format natively supported by JavaScript. JSON documents are typically 30-60% smaller, faster to parse, and universally supported by modern REST APIs and document databases. See the comparison table above for a full breakdown.
How do I store converted JSON in Couchbase from C#? Use the Couchbase .NET SDK 3.x (NuGet: CouchbaseNetClient). Connect to your Couchbase cluster or Capella endpoint, get a reference to a collection, and call collection. UpsertAsync(documentId, jsonObject). The SDK accepts JObject (from Newtonsoft) or any .NET POCO. See the code example in the “Storing in Couchbase” section above.
Should I use Newtonsoft Json.NET or System.Text.Json? For XML migration scenarios, Newtonsoft Json.NET is the better choice – it has native XML-to-JSON conversion via SerializeXmlNode(). For new .NET 6+ projects that don’t involve XML, System.Text.Json is the preferred option: it is built in, allocation-efficient, and performs better in high-throughput scenarios.
Conclusión
Converting XML to JSON in C# is straightforward with Newtonsoft Json.NET’s SerializeXmlNode method. The main considerations are attribute handling (@ prefix convention), repeated element array coercion, and namespace stripping. Once converted, the Couchbase .NET SDK makes it simple to store the resulting JSON documents in Couchbase Capella or Server using UpsertAsync.
This blog post was inspired by an email conversation with a Couchbase user. If you have any suggestions on tools, tips, or tricks to make this process easier, please let me know. Or, contact me if there’s something you’d like to see me blog about! You can envíame un correo electrónico o contact me @mgroves on X.