-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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
Be able to support custom inheritance discriminator field #1331
Comments
Heck, out there are people using all sort of field names. I'm really curious why is this a constant with no options to override. |
Because you have to draw a line at what point you stop allow customization. I have decided to draw the line here. |
@JamesNK Ok, but know that this isn't a purely visual preference. There are a lot of different field names used for that purpose and it really hampers json.net in such case when field isn't named $type. |
@JamesNK I seems to understand the tradeoff problematic you're dealing with, note that this customization line has been crossed in other popular language libraries such as the Jackson (Java) (example here : https://gist.github.com/christophercurrie/8939489 and is by example leveraged in the Swagger-Codegen). That does not off course means you have to embrace it too but I think the request is not either unreasonable. |
A workaround implementation can be found here: https://github.com/manuc66/JsonSubTypes |
@manuc66 Nice. |
I ran into the same problem. It is very problematic to use JSON.NET for deserialization GraphQL responses with interfaces fields because GraphQL uses In my opinion the choice of a constant for a discriminator is a short-sighted decision. These steps simply prohibit / complicate any adaptation of the library to different environments. Instead of a simple, effective setup, the library itself has to resort to writing unnecessary converters, which complicate the process and reduce productivity. |
I solved this problem with a custom JsonConverter. My solution borrows from Source code for Example usage: [JsonConverter(typeof(DiscriminatedJsonConverter), typeof(AnimalDiscriminatorOptions))]
public class Animal
{
private string ClassName { get; set; } // not mandatory
private string Color { get; set; }
}
// MUST have a parameterless ctor so it can be instantiated with Activator.CreateInstance
public class AnimalDiscriminatorOptions : DiscriminatorOptions
{
public override Type BaseType => typeof(Animal);
public override string DiscriminatorFieldName => "className";
// true if you want to set the value of ClassName, false to skip it
public override bool SerializeDiscriminator => false;
public override IEnumerable<(string TypeName, Type Type)> GetDiscriminatedTypes()
{
yield return ("Cat", typeof(Cat));
yield return ("Dog", typeof(Dog));
}
} |
Another issue with the choice of the Although it's possible to write a custom converter as seen in this thread, it sure would be nice to be able to change the name value without having to write a custom converter. I do understand @JamesNK 's point that you need to draw a line somewhere, but perhaps that line can be reconsidered? :) |
Not allowing the type discriminator also prevents from properly serializing/deserializing OData formatted documents, which use |
@JamesNK - The number of times this flexibility is requested makes your choice to "draw the line" a little odd. Today, working with another ecosystem and I can't just force your convention upon it. Yet somehow, I need to be compatible. Wat du? 😆 I understand in software when people need to draw a line, but this is usually done in response to adding novel functionality. Not in imposing limitations, which you must admit makes drawing the line a bit disingenuous. Please reconsider. |
@atrauzzi I used Linq-to-Json to overcome that limitation in my mobile client app.
Now I'm adding a web client and will remove the above code. I was trying to be efficient by serving BSON straight from MongoDB but, since the browser is slow with BSON, I'll instead serve it JSON. Because of this, I may as well deserialize the BSON into POCOs before reserializing it for transport to the client. What will I use to reserialize? JSON.NET of course. So I'll no longer need that client-side preprocessing. Basically, I'm giving up on my custom toolchain for transporting data from server to client. I generally like to innovate but I've concluded that this isn't an area in which to do it. It's not worth the aggravation since it'll make communicating with new systems more difficult, and it'll be more work than you expected. |
Extremely surprised to find out this hasn't been implemented in Newtonsoft.Json yet. We now have to interface with a REST API that returns a few hierarchies and uses a discriminator field called |
@JamesNK please, I urge you to re-visit and reconsider your position on this. It's such a basic, fundamental capability which has been requested by so many people over the years. If everyone who used NJ did so for both serialization and deserialization across all projects then it wouldn't be such a big deal, but that’s simply not the reality of modern software development. It's absolutely critical that the impedance match between core sub-systems like NJ and all the other building blocks we use is as high as possible. Forcing your users to resort to dodgy hacks like string-replace on the json itself can only serve to undermine the security and stability of your product, as well as any applications that rely upon it. |
@JamesNK, I found at least 20 publications and countless discussions on ways around this limitation placed, I presume, in attempt to impose own industry standard. It is simply sad, such a waste of time and effort - on both sides. |
@JamesNK with all due respect, you are clearly off in your decision on this. Please rectify this problem. It's beyond annoying and you trying to impose your own conventions on third-party systems just plain doesn't work. |
I am sure that these problems, like many others, have never been resolved. We should be honest to ourselves - JSON.NET project is dead in a sense of evolution. STJ is a replacement. JSON.NET will work for many-many years, good library (and one of the most known in NET ecosystem), but it's golden age is over. Over 600 issues and 75 PRs. It is frozen in the current state. |
@sungam3r don't disagree, unfortunately System.Text.JSON still has deal-breakers that prevent us from migrating – such as opt-ing in properties into serialization (dotnet/runtime#30180) – which apparently the STJ team doesn't even plan on taking on, thus we have no migration path into it. Stuck between a rock and a hard place. |
A bit off-topic, but I can recommend using If performance is a concern, you can do something similar with |
Of course STJ does not allow you to do whatever you want. I told about evolution. STJ moves forward. NSJ is dead. That is what I'm talking about. I see how issues number grows every year. I see a lot of abandoned PRs without any feedback from repo owner. I think this is a question not only of technical development but also MS policy. This project is a completed one staying with minimal support for the most critical bugs and it makes no sense for MS to invest in it anymore. |
@sungam3r if this is really the case (and I'm not necessarily saying it isn't...) it should be made official somewhere. Right now there is no expectation that this library is just in "support mode" or anything of the sort as, AFAIK, no statements have been made on that front at all. Even Microsoft themselves recommend using Newtonsoft.Json in some of their documentation when one needs features that are not present in STJ. Not supporting it further, while there is still no feature-parity between it and STJ, would be a big mistake IMHO. @JamesNK can you clarify on this please? |
Exactly. I asked about that somewhere else in this repo. |
Imagine refactoring the entire system for 5 days straight, assuming that little feature is obviously there, so you can just go ahead and turn it on at the end, but then get surprised that hard... And even the custom converter posted above is 500 lines of code manually iterating through the JSON jeez. |
Source JSON
destination types
Expected behavior
Be able to serialize the given json with few elegant configuration properties. Concretely if we were able to configure by some way the
JsonTypeReflector.TypePropertyName
per inheritance hierarchy it might help us.This would be very helpful to support the
@type
: https://json-ld.org/spec/ED/json-ld-syntax/20120522/#typed-valuesActual behavior
Actually we are forced to implement some sub-optimal/complex solutions, see: https://stackoverflow.com/questions/9490345/json-net-change-type-field-to-another-name
The text was updated successfully, but these errors were encountered: