如何用Newtonsoft或其他工具将指定XML转为兼容API的JSON格式
Hey there, let's fix this XML-to-JSON mismatch with your target API. The most common issues here are things like single <Item> nodes getting converted to objects instead of arrays, date format mismatches, numeric fields being serialized as strings, or naming conventions not aligning with what the API expects. Let's walk through practical solutions based on your XML snippet.
First, let's assume your full XML looks something like this (filling in the truncated part):
<packages> <Package> <trackingNumber>23780498191986</trackingNumber> <shipCost>14</shipCost> <shipDate>2018-04-12T15:33:39.887</shipDate> <items> <Item> <dscoItemId>sdsd</dscoItemId> <sku>sdsd</sku> <quantity>1</quantity> </Item> </items> </Package> </packages>
1. Force Arrays for Single Nodes (Most Common Fix)
Newtonsoft's default behavior converts single XML nodes to JSON objects instead of arrays, but most APIs expect arrays even for single items. Use the XmlNodeConverter with ForceArray to explicitly specify which nodes should always be arrays:
using Newtonsoft.Json; using Newtonsoft.Json.Converters; using System.Xml; // Load your XML string var xmlDoc = new XmlDocument(); xmlDoc.LoadXml(yourXmlContent); // Configure serialization settings var serializerSettings = new JsonSerializerSettings { Converters = new List<JsonConverter> { new XmlNodeConverter { // Force <Item> nodes to always become arrays, even if only one exists ForceArray = new List<string> { "Item" } } }, // Match the API's expected date format DateFormatString = "yyyy-MM-ddTHH:mm:ss.fff", // Ensure numeric values stay as numbers (not strings) FloatParseHandling = FloatParseHandling.Decimal }; // Convert to JSON var compatibleJson = JsonConvert.SerializeXmlNode(xmlDoc, Formatting.Indented, serializerSettings);
2. Use Entity Class Mapping (Most Reliable Long-Term Solution)
If the API has a defined JSON schema, mapping your XML to strongly-typed C# classes first gives you full control over the output. This avoids any unexpected conversion quirks:
Step 1: Define matching classes
public class PackageRequest { [JsonProperty("packages")] public List<Package> Packages { get; set; } } public class Package { [JsonProperty("trackingNumber")] public string TrackingNumber { get; set; } [JsonProperty("shipCost")] public decimal ShipCost { get; set; } [JsonProperty("shipDate")] public DateTime ShipDate { get; set; } [JsonProperty("items")] public List<Item> Items { get; set; } } public class Item { [JsonProperty("dscoItemId")] public string DscoItemId { get; set; } [JsonProperty("sku")] public string Sku { get; set; } [JsonProperty("quantity")] public int Quantity { get; set; } }
Step 2: Convert XML → Class → JSON
using System.Xml.Serialization; using Newtonsoft.Json; // Deserialize XML to your class var xmlSerializer = new XmlSerializer(typeof(PackageRequest)); PackageRequest request; using (var reader = new StringReader(yourXmlContent)) { request = (PackageRequest)xmlSerializer.Deserialize(reader); } // Serialize the class to JSON (fully aligned with API specs) var compatibleJson = JsonConvert.SerializeObject(request, Formatting.Indented, new JsonSerializerSettings { DateFormatString = "yyyy-MM-ddTHH:mm:ss.fff", NullValueHandling = NullValueHandling.Ignore // Optional: omit null fields if API requires it });
3. Manually Tweak the JSON (Quick Temporary Fix)
If you need a fast workaround without defining classes, convert the XML to a JObject and adjust the structure manually:
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Converters; var xmlDoc = new XmlDocument(); xmlDoc.LoadXml(yourXmlContent); // Convert XML to JObject var jsonObj = JObject.FromObject(xmlDoc, JsonSerializer.CreateDefault(new JsonSerializerSettings { Converters = new List<JsonConverter> { new XmlNodeConverter() } })); // Convert single Item object to an array if needed var itemsNode = jsonObj["packages"]["Package"]["items"]; if (itemsNode["Item"] is JObject singleItem) { itemsNode["Item"] = new JArray(singleItem); } // Optional: Rename fields if API uses different naming (e.g., snake_case) // jsonObj["packages"]["Package"]["ship_cost"] = jsonObj["packages"]["Package"]["shipCost"]; // jsonObj["packages"]["Package"].Remove("shipCost"); // Final JSON output var compatibleJson = jsonObj.ToString(Formatting.Indented);
Just make sure to cross-check the final JSON against your API's documentation to confirm all fields (types, naming, array structure) match exactly.
内容的提问来源于stack exchange,提问作者Kuldeep Shige

