Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
172 views
in Technique[技术] by (71.8m points)

c# - How to parse a JSON to get a typed instance of a class that extends JObject from Newtonsoft.Json?

I want to extend class from downloaded library (Newtonsoft json) using inheritance. Maybe this is not the best solution, but I want to understand what I missing.

So, here is the overview of the basic class I want to extend with additional method: https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Linq_JObject.htm

I create a new class, inherit from the base class and realize constructors:

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!");
    }

Next, I create the new class instance of my "custom" class:

// 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);

What do I misunderstand? With classes I create and fully control - everything works, but with this one - it does not.

Yes, I know that I can cast by type like and it will work

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

But for what reason? Why cant I proceed without implicit cast?

question from:https://stackoverflow.com/questions/65921071/how-to-parse-a-json-to-get-a-typed-instance-of-a-class-that-extends-jobject-from

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The reason the cast doesn't work is because Parse() returns a JObject. Even though Parse() is available on your specialized JObject named JObjectTotalJiraTickets, this does not mean it will suddenly return a JObjectTotalJiraTickets instead of a JObject.

Possible fix

You could create a new Parse() method that replaces the original one like so:

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;
    }
}

Note the new modifier that replaces the inherited Parse() method.

In fact, if you look at the source of JObject, you will find that it does exactly that to replace/extend the parse logic it inherited from JToken.

Avoid inheritance

Be aware though that inheritance is almost always the worst way to go. Try to avoid it if possible and look for a different approach.

"But still... why does the cast not work?"

The compiler is trying to tell you that it makes no sense to assume that every JObject is also always a JObjectTotalJiraTickets. That's like saying every Animal is always a Cat. It's not only false, it's also offensive to cats.

The other way around, however, makes sense: JObject o = new JObjectTotalJiraTickets() which is like saying every Cat is an Animal.

With the explicit cast JObjectTotalJiraTickets o = (JObjectTotalJiraTickets)new JObject() you are effectively telling the compiler that you know better and you are 100% sure the JObject instance actually is a JObjectTotalJiraTickets. The compiler will believe you, but the cast will fail at runtime.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...