You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JSON反序列化失败:含categoryID=117节点时代码报错求助

问题修复方案

错误原因分析

  • Children类型不兼容:JSON中大部分父节点的children是键值对形式的对象(如{"57": {...}}),但categoryID=117的children是空数组[],而原代码中Category类将Children定义为JObject,数组无法直接反序列化为JObject,这是导致执行失败的直接原因。
  • 数据类型不匹配:Category类中CategoryID、ParentCategoryID等字段定义为string,但JSON中对应值是数字或null,虽Json.NET有隐式转换,但容易引发类型异常。
  • 类结构冗余:ChildCategory和Category结构高度重复,没必要单独定义,用递归结构更合理。

修复步骤

1. 统一处理Children的类型差异

自定义JsonConverter,识别children字段的类型(数组或对象),将空数组转换为空字典,保证类型兼容。

2. 修正数据类型匹配

将Category类中数字类型字段改为int或int?(支持null),匹配JSON中的数据类型。

3. 简化类结构

删除ChildCategory类,用Dictionary<string, Category>存储子节点,通过递归结构处理嵌套层级。

完整修复代码

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;

public class Category
{
    [JsonProperty("categoryID")]
    public int CategoryID { get; set; }

    [JsonProperty("name")]
    public string Name { get; set; }

    [JsonProperty("description")]
    public string Description { get; set; }

    [JsonProperty("parentCategoryID")]
    public int? ParentCategoryID { get; set; }

    [JsonProperty("countDiscussions")]
    public int CountDiscussions { get; set; }

    [JsonProperty("countComments")]
    public int CountComments { get; set; }

    [JsonProperty("children")]
    [JsonConverter(typeof(ChildrenConverter))]
    public Dictionary<string, Category> Children { get; set; } = new Dictionary<string, Category>();
}

public class ChildrenConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(Dictionary<string, Category>);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var token = JToken.Load(reader);
        if (token.Type == JTokenType.Array)
        {
            // 空数组转换为空字典
            return new Dictionary<string, Category>();
        }
        else if (token.Type == JTokenType.Object)
        {
            // 对象直接反序列化为字典
            return token.ToObject<Dictionary<string, Category>>(serializer);
        }
        return null;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        serializer.Serialize(writer, value);
    }
}

public class Program
{
    public static void Main()
    {
        string jsonData = @"[
        {   
            ""categoryID"": 93,
            ""name"": ""Cloths"",
            ""description"": """",
            ""parentCategoryID"": null,
            ""countDiscussions"": 10,
            ""countComments"": 20,
            ""children"": {
                ""57"": {
                    ""categoryID"": 180,
                    ""name"": ""Shirt"",
                    ""description"": """",
                    ""parentCategoryID"": 9,
                    ""countDiscussions"": 2,
                    ""countComments"": 4,
                    ""children"": []
                },
                ""56"": {
                    ""categoryID"": 187,
                    ""name"": ""ShirtAAAAA"",
                    ""description"": """",
                    ""parentCategoryID"": 9,
                    ""countDiscussions"": 2,
                    ""countComments"": 4,
                    ""children"": []
                }
            }
        },
        {
            ""categoryID"": 172,
            ""name"": ""accessories"",
            ""description"": """",
            ""parentCategoryID"": null,
            ""countDiscussions"": 15,
            ""countComments"": 47,
            ""children"": {
                ""2"": {
                    ""categoryID"": 191,
                    ""name"": ""Watch"",
                    ""description"": """",
                    ""parentCategoryID"": 172,
                    ""countDiscussions"": 1,
                    ""countComments"": 0,
                    ""children"": []
                }
            }
        },
        {
            ""categoryID"": 117,
            ""name"": ""jewellery"",
            ""description"": """",
            ""parentCategoryID"": null,
            ""countDiscussions"": 243,
            ""countComments"": 6716,
            ""children"": []
        }
    ]";

        var categories = JsonConvert.DeserializeObject<Category[]>(jsonData);

        foreach (var category in categories)
        {
            Console.WriteLine($"Category ID: {category.CategoryID}");
            Console.WriteLine($"Name: {category.Name}");
            Console.WriteLine($"Description: {category.Description}");
            Console.WriteLine($"Parent Category ID: {category.ParentCategoryID ?? 0}");
            Console.WriteLine($"Count of Discussions: {category.CountDiscussions}");
            Console.WriteLine($"Count of Comments: {category.CountComments}");
            Console.WriteLine("Children:");
            foreach (var childEntry in category.Children)
            {
                var child = childEntry.Value;
                Console.WriteLine($"    Key: {childEntry.Key}");
                Console.WriteLine($"    Category ID: {child.CategoryID}");
                Console.WriteLine($"    Name: {child.Name}");
                Console.WriteLine($"    Description: {child.Description}");
                Console.WriteLine($"    Parent Category ID: {child.ParentCategoryID ?? 0}");
                Console.WriteLine($"    Count of Discussions: {child.CountDiscussions}");
                Console.WriteLine($"    Count of Comments: {child.CountComments}");
            }
            Console.WriteLine("------------------------");
        }
    }
}

修复说明

  1. 自定义转换器:ChildrenConverter自动处理children字段的类型差异,空数组转为空字典,避免转换异常。
  2. 类型匹配:将数字类字段改为int/int?,完美适配JSON中的数字和null值,消除类型转换风险。
  3. 递归结构:用Dictionary<string, Category>存储子节点,既符合JSON的键值对结构,又支持无限层级的嵌套子节点解析。
  4. null值处理:输出时用?? 0将null替换为0,也可根据需求改为显示"null"。

内容的提问来源于stack exchange,提问作者Sreepu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 05:10:22