反序列化JSON报错:无法将JObject转换为JArray问题咨询
Hey there, let's break down this deserialization bug you're facing—it’s super common when JSON structures shift from arrays to single objects, and your hunch about StressTestResults being the culprit is spot-on!
The error Unable to cast object of type 'Newtonsoft.Json.Linq.JObject' to type 'Newtonsoft.Json.Linq.JArray' happens because Newtonsoft.Json is trying to convert a single JSON object ({...}) into an array/list type, which doesn’t match. Here’s exactly what’s going on:
- Before: Your JSON had
StressTestResultsas a proper array ([...]), so your code (expecting an array/list type) deserialized it without issues. - After: The updated JSON returns
StressTestResultsas a single key-value object ({...}), but yourTrigger2Outputclass still expects an array/list for that property—hence the type mismatch error.
Example JSON Comparison
Working JSON (array format):
{ "SomeOtherField": "test data", "StressTestResults": [ {"TestId": 1, "Status": "Pass"}, {"TestId": 2, "Status": "Fail"} ] }Broken JSON (single object format):
{ "SomeOtherField": "new test data", "StressTestResults": {"TestId": 3, "Status": "Pass"} }
Your Trigger2Output Class (Likely Structure)
Your class is probably defined with an array/list property for StressTestResults, like this:
public class Trigger2Output { // Other properties... public List<StressTestResult> StressTestResults { get; set; } // Or using JArray directly: // public JArray StressTestResults { get; set; } } public class StressTestResult { public int TestId { get; set; } public string Status { get; set; } }
You’ve got three solid options to fix this, depending on whether you can control the JSON source:
1. Fix the JSON Source (If Possible)
The simplest fix: Ask whoever owns the JSON endpoint to always return StressTestResults as an array—even if there’s only one result. So instead of {"TestId":3,...}, it should be [{"TestId":3,...}]. No code changes needed on your end!
2. Use a Custom JSON Converter (Best for Uncontrollable JSON)
Add a converter that tells Newtonsoft.Json to handle both single objects and arrays for the StressTestResults property. First, create the converter:
public class SingleOrArrayConverter<T> : JsonConverter { public override bool CanConvert(Type objectType) { return objectType == typeof(T); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var token = JToken.Load(reader); return token.Type switch { JTokenType.Array => token.ToObject<T>(), JTokenType.Object => new JArray(token).ToObject<T>(), _ => throw new JsonSerializationException($"Unexpected token type: {token.Type}") }; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { serializer.Serialize(writer, value); } }
Then apply it to your Trigger2Output property:
public class Trigger2Output { // Other properties... [JsonConverter(typeof(SingleOrArrayConverter<List<StressTestResult>>))] public List<StressTestResult> StressTestResults { get; set; } }
Now your code will automatically convert single objects into a list with one item, and arrays into a full list.
3. Manually Handle Type Checking (Quick & Flexible)
If you don’t want to add a custom converter, parse the JSON into a JObject first and manually check the type of StressTestResults:
var jsonInput = "your updated JSON string"; var jObj = JObject.Parse(jsonInput); var output = new Trigger2Output(); // Map other properties normally output.SomeOtherField = jObj["SomeOtherField"].ToString(); // Handle StressTestResults var stressTestToken = jObj["StressTestResults"]; if (stressTestToken.Type == JTokenType.Array) { output.StressTestResults = stressTestToken.ToObject<List<StressTestResult>>(); } else if (stressTestToken.Type == JTokenType.Object) { var singleResult = stressTestToken.ToObject<StressTestResult>(); output.StressTestResults = new List<StressTestResult> { singleResult }; }
This gives you full control over how the data is mapped, which is great for one-off fixes or messy JSON structures.
To confirm your hunch, run this quick check on the problematic JSON:
var testJObj = JObject.Parse("your broken JSON"); Console.WriteLine(testJObj["StressTestResults"].Type);
It will output JObject instead of JArray, confirming exactly where the mismatch is.
内容的提问来源于stack exchange,提问作者Tom

