如何修复C#中JSON反序列化类型错误?附JSON示例与代码片段
It looks like your JSON structure and the C# type you're trying to deserialize into don't match up—that's almost always the root cause of these type errors. Let's break down the problem and fix it step by step.
First, Let's Clarify Your JSON Structure
Your JSON is a single key-value object where the key is the card name ("Adorable Kitten") and the value holds the card's details:
{ "Adorable Kitten": { "layout": "normal", "name": "Adorable Kitten", "manaCost": "{W}", "cmc": 1, "colors": ["White"], "type": "Host Creature — Cat", "types": ["Host","Creature"], "subtypes": ["Cat"], "text": "When this creature enters the battlefield, roll a six-sided die. You gain life equal to the result.", "power": "1", "toughness": "1", "imageName": "adorable kitten", "colorIdentity": ["W"] } }
If you're trying to deserialize this directly into a List<Card>, that's why you're getting an error—your JSON isn't an array (which uses []), it's a single key-value pair object.
Step 1: Define the Correct C# Card Model
First, create a class that exactly matches the properties in your JSON (pay close attention to data types):
public class Card { public string Layout { get; set; } public string Name { get; set; } public string ManaCost { get; set; } public int Cmc { get; set; } // Cmc is a number in JSON, so use int here public List<string> Colors { get; set; } public string Type { get; set; } public List<string> Types { get; set; } public List<string> Subtypes { get; set; } public string Text { get; set; } public string Power { get; set; } // Power/toughness can be symbols like *, so use string public string Toughness { get; set; } public string ImageName { get; set; } public List<string> ColorIdentity { get; set; } }
Step 2: Choose the Right Deserialization Approach
Pick one of these options based on your needs:
Option 1: Deserialize into a Dictionary (Best for Multiple Cards)
If your JSON might eventually include multiple cards (each with their name as the key), use a Dictionary<string, Card>:
Using System.Text.Json (built into .NET):
using (StreamReader reader = new StreamReader("your-card-file.json")) { string jsonContent = reader.ReadToEnd(); var cardDictionary = JsonSerializer.Deserialize<Dictionary<string, Card>>(jsonContent); // Access your card like this: Card adorableKitten = cardDictionary["Adorable Kitten"]; }
Using Newtonsoft.Json (popular third-party library):
using (StreamReader reader = new StreamReader("your-card-file.json")) { string jsonContent = reader.ReadToEnd(); var cardDictionary = JsonConvert.DeserializeObject<Dictionary<string, Card>>(jsonContent); Card adorableKitten = cardDictionary["Adorable Kitten"]; }
Option 2: Extract the Single Card Directly
If you only ever expect one card in the JSON, you can parse it as a JObject first (requires Newtonsoft.Json):
using (StreamReader reader = new StreamReader("your-card-file.json")) { string jsonContent = reader.ReadToEnd(); JObject cardObject = JObject.Parse(jsonContent); Card adorableKitten = cardObject["Adorable Kitten"].ToObject<Card>(); }
Option 3: Adjust the JSON to Be an Array (If You Need a List)
If you really want to deserialize into a List<Card>, modify your JSON to wrap the card in an array ([]):
[ { "layout": "normal", "name": "Adorable Kitten", "manaCost": "{W}", "cmc": 1, "colors": ["White"], "type": "Host Creature — Cat", "types": ["Host","Creature"], "subtypes": ["Cat"], "text": "When this creature enters the battlefield, roll a six-sided die. You gain life equal to the result.", "power": "1", "toughness": "1", "imageName": "adorable kitten", "colorIdentity": ["W"] } ]
Then deserialize like this:
using (StreamReader reader = new StreamReader("your-card-file.json")) { string jsonContent = reader.ReadToEnd(); List<Card> cardList = JsonSerializer.Deserialize<List<Card>>(jsonContent); }
Common Pitfalls to Avoid
- Data Type Mismatches: Ensure your C# class properties match the JSON data types (e.g.,
cmcis an integer in JSON, so don't usestringin your model). - Case Sensitivity: By default,
System.Text.Jsonis case-sensitive. If your JSON uses camelCase (likeimageName) but your class uses PascalCase (likeImageName), configure the serializer to ignore case:var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; var cardDictionary = JsonSerializer.Deserialize<Dictionary<string, Card>>(jsonContent, options);
内容的提问来源于stack exchange,提问作者drako234

