Comments (10)
Hi @sanzor
It's not supported, but if you have both:
- a field in Child1 that is not in Child2
- a field in Child2 that is not in Child1
You can use JsonSubtypes.KnownSubTypeWithProperty
:
public class Parent{
Child childField {get;set;}
}
[JsonConverter(typeof(JsonSubtypes))]
[JsonSubtypes.KnownSubTypeWithProperty(typeof(Child1), "FieldChild1")]
[JsonSubtypes.KnownSubTypeWithProperty(typeof(Child2), "FieldChild2")]
public abstract class Child {
}
public class Child1 : Child{
public int FieldChild1 {get;set;}
}
public class Child2 : Child{
public bool FieldChild2 {get;set;}
}
And a JSON without discriminator field:
{
"childField": { "FieldChild2": true }
}
from jsonsubtypes.
Thank you very much for your answer !
from jsonsubtypes.
I am facing the same issue. Do you think this might be possible to achieve with this library?
If so, do you have any hint where I might get started? Maybe I try to implement that.
from jsonsubtypes.
Note that there is also this UGLY solution if you're really blocked:
public enum Discriminator{
Child1=0,
Child2=1
}
[JsonConverter(typeof(JsonSubTypes), "Kind")]
[JsonSubTypes.KnownSubTypes(typeof(ParentWithChild1), Discriminator.Child1)]
[JsonSubTypes.KnownSubTypes(typeof(ParentWithChild2), Discriminator.Child2)]
public class Parent {
public abstract Discriminator Kind {get;}
}
public class ParentWithChild1 {
public Child1 childField {get ;set;}
public override Kind=>Discriminator.Child1;
}
public class ParentWithChild2 {
public Child2 childField {get; set;}
public override Kind=>Discriminator.Child2;
}
public abstract class Child {
}
public class Child1 : Child{
public int FieldChild1 {get; set;}
}
public class Child2 : Child{
public bool FieldChild2 {get; set;}
}
By the way a proper implementation should first find a way to declare the relation elegantly, a proposal could be :
[JsonConverter(typeof(JsonWithDiscriminatedProperty))]
[JsonResolvePropertySubtypes("childField",
new object[] { Discriminator.Child1, Discriminator.Child2 },
new[] { typeof(Child1), typeof(Child2) })]
public class Parent
{
Child childField { get; set; }
}
especially the fact that there is no way to ensure at compile time that the array are the same dimensions and It's not either easy to read. (Not that it could allow to multiple discriminated fields)
I've also thought to this:
[JsonConverter(typeof(JsonWithDiscriminatedSubtypeProperty), "kindFieldA")]
[JsonResolvePropertyValueWithSubtypes(Discriminator.Child1, typeof(Child1))]
[JsonResolvePropertyValueWithSubtypes(Discriminator.Child2, typeof(Child1))]
public class Parent
{
public Discriminator kindFieldA { get; }
Child childField { get; set; }
}
but there is nothing that make the link between the kind property and the discriminated child... (in case of multiple discriminated property with the same base type)
I'm open to propositions
from jsonsubtypes.
Thanks for your prompt replay and the effort you put into this.
To tell the truth, I didn't think a whole lot about how to configure it. And I also have to admit, that I am not blocked by this right now. I am guaranteed to have no nesting of those types, so I can just use bare Json.Net to convert the object and then continue to parse the returned JObject into the correct child type.
But since others might have the same problem, I will try to give more details. Maybe this can help to decide for an approach to annotate this.
My Json looks like this:
{
"ContentType": "TypeA",
"Payload": {
"Name": "Joe"
}
}
and
{
"ContentType": "TypeB",
"Payload": {
"Number": 42
}
}
The parent C# class might look like
public class Parent
{
public string ContentType {get; set;} // Might be an enum
public Child Payload {get; set;}
}
So I could imagine an annotation similar to your last example:
[JsonConverter(typeof(JsonWithDiscriminatedSubtypeProperty), "ContentType")]
[JsonResolvePropertyValueWithSubtypes("TypeA", typeof(ChildTypeA))]
[JsonResolvePropertyValueWithSubtypes("TypeB", typeof(ChildTypeB))]
public class Parent
{
public string ContentType {get; set;} // Might be an enum
public Child Payload {get; set;}
}
Do you think this can be implemented?
from jsonsubtypes.
Hi @Peter-B- ,
I think that this solution is implementable but will have limitation: no possibility to handle multiple discriminated property because only one JsonWithDiscriminatedSubtypeProperty
(JsonConverter) will be instantiated.
[JsonConverter(typeof(JsonWithDiscriminatedSubtypeProperty), "ContentType")] [JsonResolvePropertyValueWithSubtypes("TypeA", typeof(ChildTypeA))] [JsonResolvePropertyValueWithSubtypes("TypeB", typeof(ChildTypeB))] public class Parent { public string ContentType {get; set;} // Might be an enum public Child Payload {get; set;} }
=> I would prefer a solution that does not come with this limitation
The implementation of this feature is technically feasible but the complexity is not 'trivial', from my point of view it should refactor JsonSubtypes.cs
and :
- re-use the trick behind
_isInsideRead
logic (see discussion inside this PR #39 ) - re-use the array/collection reading (to support a
public List<Child> Payload {get; set;}
) - re-use type find algorithm
- still provide(*) the possibility to support runtime configuration (similarly to
JsonSubtypesConverterBuilder
) - serializing and provide(*) the possibility to auto inject the discriminator in the json
- ...
(*): or consider that it will possible to later add
from jsonsubtypes.
What about something like this:
[JsonConverter(typeof(JsonPropertySubTypes))]
public class Parent
{
public string ContentType1 {get; set;} // Might be an enum
[JsonSubTypes.ResolveWithProperty(nameof(ContentType1))
public Child Payload1 {get; set;}
public string ContentType2 {get; set;} // Might be an enum
[JsonSubTypes.ResolveWithProperty(nameof(ContentType2))
public Child Payload2 {get; set;}
}
[JsonSubTypes.KnownSubTypes(typeof(ChildTypeA), "TypeA")]
[JsonSubTypes.KnownSubTypes(typeof(ChildTypeB), "TypeB")]
public class Child
{
}
from jsonsubtypes.
That is exactly my scenario. I also think the syntax is quite readable - at least way better than the workaround from above.
Do you think this is easy to implement or do you anticipate large architectural changes?
from jsonsubtypes.
It does not depend on a lot of existing code, if you implement it with another custom converter it could be done this way:
public class SomeClasswWithTwoAbstract : JsonConverter
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
JsonSerializer serializer)
{
var parent = new Parent();
var json = JObject.Load(reader);
var parentType = typeof(Child);
var parentTypeFullName = parentType.FullName;
var searchLocation = parentTypeFullName.Substring(0, parentTypeFullName.Length - parentType.Name.Length);
var typeName1 = json["ContentType1"].Value<string>();
var typeName2 = json["ContentType2"].Value<string>();
var contentType1 = parentType.Assembly.GetType(searchLocation + typeName1, false, true);
var contentType2 = parentType.Assembly.GetType(searchLocation + typeName2, false, true);
parent.Payload1 = (Child) serializer.Deserialize(CreateAnotherReader(json["Payload1"], reader), contentType1);
parent.Payload2 = (Child) serializer.Deserialize(CreateAnotherReader(json["Payload2"], reader), contentType2);
return parent;
}
private static JsonReader CreateAnotherReader(JToken jToken, JsonReader reader)
{
// duplicate code
var jObjectReader = jToken.CreateReader();
jObjectReader.Culture = reader.Culture;
jObjectReader.CloseInput = reader.CloseInput;
jObjectReader.SupportMultipleContent = reader.SupportMultipleContent;
jObjectReader.DateTimeZoneHandling = reader.DateTimeZoneHandling;
jObjectReader.FloatParseHandling = reader.FloatParseHandling;
jObjectReader.DateFormatString = reader.DateFormatString;
jObjectReader.DateParseHandling = reader.DateParseHandling;
return jObjectReader;
}
}
See the working sample: https://dotnetfiddle.net/nv1EpP
from jsonsubtypes.
Maybe #91 will help
from jsonsubtypes.
Related Issues (20)
- Support Enums HOT 2
- Misleading error message on deserialization when subtype is unknown HOT 1
- Allow to disable behavior introduced by fix #100 in 1.8.0 - Stop StopLookupOnMatch HOT 2
- Incorrect link to license
- New Major to depend on newer Newtonsoft.Json HOT 3
- KnownSubTypeWithProperty it would be great to support aliases HOT 3
- Support (serializing) sub types with generic type parameters when using JsonSubtypesConverterBuilder HOT 7
- MaxDepth not copied over when creating internal JsonReader
- Serialize type discriminator when using attributes too HOT 6
- Use in API calls?
- Example code in readme fails, just completely wrong according to visual studio HOT 1
- JsonSubtypesConverterBuilder SetFallbackSubtype HOT 1
- wrong link in v2.0.1 release notes HOT 1
- JsonReaderException does not contain a constructor that takes 5 arguments HOT 4
- Persistent settings HOT 1
- Base Class Properties not being Deserialized HOT 2
- Outdated version of NewtsonSoft.Json used
- deserializing dates with jsonsubtypes does not match same result values as stock newtonsoft
- Error on deserialization "Could not find member ... on type" when MissingMemberHandling=error and there is no discriminator field on the dto HOT 1
- Support combination of independent discriminator types per inheritance level HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from jsonsubtypes.