如何解析 JSON 以获取从 Newtonsoft.Json 扩展 JObject 的类的类型化实例?

问题描述

我想使用继承从下载的库(Newtonsoft json)中扩展类。也许这不是最好的解决方案,但我想了解我错过了什么。

所以,这里是我想用附加方法扩展的基本类的概述: https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Linq_JObject.htm

我创建了一个新类,从基类继承并实现构造函数

public class JObjectTotalJiraTickets : JObject
{
    public JObjectTotalJiraTickets(string json) : base(json) { }
    public JObjectTotalJiraTickets(Object o) : base(o) { }
    public JObjectTotalJiraTickets(Object[] o) : base(o) { }
    public JObjectTotalJiraTickets(JObject jo) : base(jo) { }

    public void sayhello()
    {
        Console.WriteLine("Hello!");
    }

接下来,我创建我的“自定义”类的新类实例

// Here I get error CS0266 (Cannot implicitly convert type 'Newtonsoft.json.linq.JObject' to 'JObjectTotalJiraTickets)
// And propose IDE0002 (Name can be simplified),with the solution to change my type just to JObject class.
JObjectTotalJiraTickets o = JObjectTotalJiraTickets.Parse(json);

我误解了什么?使用我创建并完全控制的类 - 一切正常,但使用这个类 - 它没有。

是的,我知道我可以按类型进行转换,它会起作用

JObjectTotalJiraTickets o = (JObjectTotalJiraTickets)JObjectTotalJiraTickets.Parse(json);

但是什么原因呢?为什么我不能在没有隐式转换的情况下继续?

解决方法

强制转换不起作用的原因是因为 Parse() 返回一个 JObject。尽管 Parse() 在名为 JObject 的专用 JObjectTotalJiraTickets 上可用,但这并不意味着它会突然返回 JObjectTotalJiraTickets 而不是 JObject

可能的修复

您可以创建一个新的 Parse() 方法来替换原来的方法,如下所示:

public class JObjectTotalJiraTickets : JObject
{
    public static new JObjectTotalJiraTickets Parse(string json)
    {
        // Re-use base class parse logic.
        var jobj = JObject.Parse(json);

        // Your logic to create a `JObjectTotalJiraTickets` from a `JObject`.
        JObjectTotalJiraTickets myjobj = DoTheJiraThings(jobj)

        return myjobj;
    }
}

注意替换继承的 new 方法的 Parse() 修饰符。

事实上,如果你查看JObject的来源,你会发现它做了exactly that来替换/扩展parse logic it inherited from JToken

避免继承

请注意,虽然继承几乎总是 the worst way to go。如果可能,尽量避免它并寻找不同的方法。

“但仍然......为什么演员阵容不起作用?”

编译器试图告诉您,假设每个 JObject 也总是一个 JObjectTotalJiraTickets 是没有意义的。这就像说每个 Animal 总是一个 Cat。不仅是假的,对猫也是一种冒犯。

然而,反过来说是有道理的:JObject o = new JObjectTotalJiraTickets() 就像说每个 Cat 都是一个 Animal

通过显式转换 JObjectTotalJiraTickets o = (JObjectTotalJiraTickets)new JObject(),您可以有效地告诉编译器您知道得更好,并且您 100% 确定 JObject 实例实际上是一个 JObjectTotalJiraTickets。编译器会相信你,但转换会在运行时失败。