Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support of per inheritance level discriminators #60

Closed
sanzor opened this issue Feb 23, 2019 · 3 comments
Closed

Support of per inheritance level discriminators #60

sanzor opened this issue Feb 23, 2019 · 3 comments
Milestone

Comments

@sanzor
Copy link

sanzor commented Feb 23, 2019

If i have a 3-level hierarchy and i place a JsonProperty at first and second level

Animal     
Dog:Animal
Husky:Dog

Can i deserialize like:


var dog=new Husky();
var data= JsonConvert.SerializeObject<Husky>();
Animal a=JsonConvert.DeserializeObject<Animal>();

So far i get an error and i can only deserialize it like this:
Animal a=JsonConvert.DeserializeObject<Dog>();

P.S My question is better seen here https://stackoverflow.com/questions/54835920/deserializing-with-multiple-levels-of-polymorphic-type-hierarchy

Sample code:

using System;
using Newtonsoft.Json;
using JsonSubTypes;

namespace Test60
{
    class Program
    {
        static void Main(string[] args)
        {
            Payload run = new Payload.Game.Run();
            var data = JsonConvert.SerializeObject(run);
            Console.WriteLine(data);
            var run2 = JsonConvert.DeserializeObject<Payload>(data);
            Console.WriteLine("Hello World!");
        }
    }
    [JsonConverter(typeof(JsonSubTypes.JsonSubtypes), _payloadKind)]
    [JsonSubtypes.KnownSubType(typeof(Payload.Game), Discriminator.GAME)]
    [JsonSubtypes.KnownSubType(typeof(Payload.Com), Discriminator.COM)]
    public abstract partial class Payload
    {
        public const string _payloadKind = "$PayloadKind";

        [JsonProperty(_payloadKind)]
        protected abstract Discriminator PayloadKind { get; }
        public Discriminator Kind => this.PayloadKind;
        public enum Discriminator
        {
            COM = 0,
            GAME = 1
        }
    }
    partial class Payload
    {
        [JsonConverter(typeof(JsonSubTypes.JsonSubtypes), GAMEKIND)]
        [JsonSubTypes.JsonSubtypes.KnownSubType(typeof(Game.Run), Discriminator.RUN)]
        [JsonSubTypes.JsonSubtypes.KnownSubType(typeof(Game.Walk), Discriminator.WALK)]
        public abstract partial class Game : Payload
        {
            protected override Payload.Discriminator PayloadKind => Payload.Discriminator.GAME;
            public new enum Discriminator
            {
                RUN = 0,
                WALK = 1
            }
            public const string GAMEKIND = "$GameKind";
            [JsonProperty(GAMEKIND)]
            protected abstract Discriminator GameKind { get; }
            public new Discriminator Kind => this.GameKind;
        }
    }


    partial class Payload
    {
        public abstract class Com : Payload
        {

        }
    }
    partial class Payload
    {
        partial class Game
        {
            public class Walk : Game
            {
                protected override Discriminator GameKind => Discriminator.WALK;
            }
        }
    }

    partial class Payload
    {
        partial class Game
        {
            public class Run : Game
            {
                protected override Discriminator GameKind => Discriminator.RUN;
            }
        }
    }
}
@manuc66
Copy link
Owner

manuc66 commented Feb 23, 2019

Hi @sanzor

This use case is not yet supported. If we look into the serialized data we can see that there are in fact three discriminator fields serialized:

{"$GameKind":0,"$PayloadKind":1,"Kind":0}

Currently when JsonSubtypes resolve the first discriminator it doesn't look if the resolved type is also annotated with JsonSubtypes.KnownSubType, that's why it doesn't work.

It's a feature that could be interesting to include in further release. I might have a look when I'll have some free time, or you can try to hack into this library and make a PR ;-)

At first look it seems that adding a loop in the function GetType might be ok

@sanzor
Copy link
Author

sanzor commented Feb 23, 2019 via email

manuc66 added a commit that referenced this issue Feb 24, 2019
@manuc66 manuc66 changed the title Does this work with multiple levels of polymorphic types? Support of per inheritance level discriminators Feb 24, 2019
@manuc66 manuc66 added this to the 1.6.0 milestone Feb 24, 2019
@sanzor
Copy link
Author

sanzor commented Feb 27, 2019

I have managed to solve this by using your library.I would keep an abstract field in the root object only to be overridden in the leaf's.I would use this field as a discriminator in the attribute.Then i would separately implement a discriminated union.
And it works like a charm even if it might be optimized i guess.

Source code is here:
https://github.com/sanzor/DUnion

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants