question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

How to achieve polymorphic behavior?

See original GitHub issue

I have a slightly complex structure where my Entity class has members property which may contains members of either Container or Action type. The $type information is also coming along in the json to identify if it is a Container or Action member with every object but how to map it to corresponding classes using this $type information?

@jsonObject
export class Entity {
    @jsonArrayMember(Member)
    public members: Member[];
}

@jsonObject
export abstract class Member {
    @jsonMember
    public id: string;

    @jsonMember
    public name: string;
}

@jsonObject
export abstract class ContainerMember extends Member {
    @jsonArrayMember(Member)
    public children: Member[];
}

@jsonObject
export class SomeConcreteContainerMember1 extends ContainerMember {
    // with additional properties
}

@jsonObject
export abstract class ActionMember extends Member {
}

@jsonObject
export class SomeConcreteActionMember1 extends ActionMember {
    // with additional properties
}

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

2reactions
krizkacommented, Dec 21, 2019

Hope, it will be helpful for someone who will search, I made some util function and new decorator to achieve polymorphic behaviour, which worked quite well for me. it is added knownTypes to root type automatically, searching for root element: https://gist.github.com/krizka/c83fb1966dd57997a1fc02625719387d

1reaction
JohnWeiszcommented, Jan 15, 2019

I assume this is coming from Json.NET (which uses the $type property with a fully-qualified name by default). TypedJSON is very similar, only it uses __type by default, which can be configured by using a custom type-resolver. However, one big difference is that TypedJSON does not use a fully-qualified name, but only the class-name, so you’ll either need to configure Json.NET to only emit the class name, or write a type-resolver that only takes the last part of the fully qualified name.

The signature of a type-resolver is the following:

(sourceObject: Object, knownTypes: Map<string, Function>) => Function;

Where sourceObject is a raw, untyped Javascript object (you inspect this object to look for a type-hint), and knownTypes is a map of references to any additional known classes used during the deserialization process. The return value is the class reference itself. These known types must be set in advance, more on that later.

This is the default type-resolver, which uses the __type property:

(sourceObject, knownTypes) => knownTypes.get(sourceObject.__type)

You can set a custom type-resolver in the configuration:

new TypedJson(Entity, {
    typeResolver: (sourceObject, knownTypes) => knownTypes.get(sourceObject.$type)
});

If Json.NET is emitting fully-qualified names, you should be able to do this:

new TypedJson(Entity, {
    typeResolver: (sourceObject, knownTypes) =>
    {
        if (sourceObject.$type)
        {
            let typeParts = sourceObject.$type.split(".")
            let className = typeParts[typeParts.length - 1];
            return knownTypes.get(className);
        }
    }
});

Now, to recognize sub-classes during deserialization, you need to set them as known types (which is basically a listof classes). You can set this in the configuration, or in the @jsonObject decorator, this must be done on the class which you expect to contain polymorphic objects:

@jsonObject({ knownTypes: [ContainerMember, SomeConcreteContainerMember1, ... ] })
export class Entity {
    @jsonArrayMember(Member)
    public members: Member[];
}

Note: you can also specify a static method by its key for knownTypes, in that case your method should return the array of known-types.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Polymorphic Behavior - IBM
Polymorphism is achieved in C++ by using inheritance and virtual functions. Consider the scenario where we have three forms (ExpenseForm, LoanForm, ...
Read more >
OOP Concepts for Beginners: What is Polymorphism - Stackify
Polymorphism is one of the core concepts in OOP languages and describes the concept wherein you can use different classes with the same ......
Read more >
Polymorphism in Java with Examples in 2023 - Great Learning
Polymorphism in Java can be defined as the ability of an object to take many forms. This helps us perform the same action...
Read more >
10.3 Demonstrating Polymorphic Behavior | Object-Oriented ...
Harvey M. Deitel and Paul J. Deitel explain and demonstrate the concept of polymorphism with inheritance hierarchies.
Read more >
What Is Polymorphism in Java and How to Implement It?
Characteristics/Features of Polymorphism · The functionality of a method behaves differently in different scenarios. · The behavior of a method ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found