C#使用Newtonsoft.Json反序列化报错:无法将类型为“Newtonsoft.Json.Linq.JObject”的对象强制转换

本文讲述了在C#中使用Newtonsoft.Json处理包含自定义ActionCollection的Cat对象序列化和反序列化时遇到的问题,介绍了如何手动修复DeserializeObject的不足并提供测试代码。
摘要由CSDN通过智能技术生成

1、问题描述

C#使用Newtonsoft.Json将 一般对象 序列化和反序列化为json时,一般使用 SerializeObject()DeserializeObject() 即可。
但是,当对象中包含一个自定义集合对象时,仅仅使用DeserializeObject() 无法正确实现反序列化。
有可能报错:

无法将类型为“Newtonsoft.Json.Linq.JObject”的对象强制转换

2、代码说明

直接用一段示例代码,进行说明。

2.1 准备阶段

示例准备3个类:
Action 类:表示一个动作。

class Action
{
    public Action()
    {
    }
    public Action(string name, int step)
    {
        m_name = name;
        m_step = step;
    }
    public override string ToString()
    {
        return $"Action Name:{m_name}, Step: {m_step.ToString()}";
    }
    private string m_name; // 动作名称
    private int m_step; // 动作步骤
    public string Name { get => m_name; set => m_name = value; }
    public int Step { get => m_step; set => m_step = value; }
}

ActionCollection 类:表示一个动作的集合类。

class ActionCollection : CollectionBase
{
    public void Add(Action action)
    {
        this.InnerList.Add(action);
    }
}

Cat 类:猫类,Cat 对象包含一个 ActionCollection 类实例。

class Cat
{
    private string m_name; // 猫的名字
    private ActionCollection m_actions; // 具备的动作集合
    public Cat()
    {
    }
    public Cat(string name, ActionCollection ac)
    {
        this.m_name = name;
        this.m_actions = ac;
    }
    public string Name { get => m_name; set => m_name = value; }
    public ActionCollection Actions { get => m_actions; set => m_actions = value; }
}

2.2 序列化

使用 SerializeObject() 方法将一个 Cat 对象序列化为Json,并存储到文件中。

/// <summary>
/// 序列化一个Cat对象到Json
/// </summary>
/// <param name="cat"></param>
/// <param name="jsonPath"></param>
public static void Save(Cat cat, string jsonPath)
{
    string jsonString = JsonConvert.SerializeObject(cat);
    File.WriteAllText(jsonPath, jsonString);
}

2.3 反序列化

简单地使用 DeserializeObject() 方法从json文件中读取json字符串,并反序列化为一个 Cat 对象。

/// <summary>
/// 反序列化(错误方法)
/// </summary>
/// <param name="jsonPath"></param>
public static Cat Load(string jsonPath)
{
    string jsonString = File.ReadAllText(jsonPath);
    Cat cat = JsonConvert.DeserializeObject<Cat>(jsonString);
    return cat;
}

使用测试代码进行调试,发现会报错:

无法将类型为“Newtonsoft.Json.Linq.JObject”的对象强制转换为Action。
在这里插入图片描述

原因说明:

简单地使用 DeserializeObject() 方法进行反序列化时,只会将 ActionCollection 集合类实例中的元素反序列化为一个JObject对象。
JObject对象无法隐式转换为Action类对象,因而会报错。

解决方案:
由于使用 DeserializeObject() 方法无法正确地将“集合对象字段”的元素反序列化出来。因此,需要手动修正。

代码如下:

/// <summary>
/// 反序列化(正确方法)
/// </summary>
/// <param name="jsonPath"></param>
/// <returns></returns>
public static Cat LoadJson(string jsonPath)
{
    string jsonString = File.ReadAllText(jsonPath);
    Cat cat = JsonConvert.DeserializeObject<Cat>(jsonString);

    ActionCollection actions = new ActionCollection();
    foreach(var item in cat.Actions)
    {
        string itemString = item.ToString();
        Action ac = JsonConvert.DeserializeObject<Action>(itemString);
        actions.Add(ac);
    }
    cat.Actions = actions;

    return cat;
}

再次使用测试代码进行调试,可以发现问题解决。
在这里插入图片描述

3、测试代码

如果需要测试报错,需要取消“错误方法取出猫”的注释。

static void Main(string[] args)
{
    // 准备一只猫
    Action run = new Action("Running", 2);
    Action jump = new Action("Jump", 2);
    ActionCollection actions = new ActionCollection();
    actions.Add(run);
    actions.Add(jump);
    Cat helloKitty = new Cat("HelloKitty", actions);

    // 将猫放入json
    string jsonPath = "cat.json";
    Save(helloKitty, jsonPath);

     错误方法取出猫
    //Cat helloKittyClone = Load(jsonPath);

    //Console.WriteLine(helloKittyClone.Name);
    //foreach (Action x in helloKittyClone.Actions)
    //{
    //    Console.WriteLine(x.ToString());
    //}

    // 正确方法取出猫
    Cat helloKittyCloneX = LoadJson(jsonPath);

    Console.WriteLine(helloKittyCloneX.Name);
    foreach (Action x in helloKittyCloneX.Actions)
    {
        Console.WriteLine(x.ToString());
    }
}

代码附件:Github传送门

以上为C#使用Newtonsoft.Json反序列化时遇到的一个问题。如果有更好的解决方案,欢迎留言交流。

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

指尖码动

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值