I want to replicate the TypeNameHandling = TypeNameHandling.Objects
setting but have my own property name, rather than $type
, and have it find the objects based on the simple class name rather than have the assembly referenced.
I have a nested object model that I am trying to sterilise using the Newtonsoft tool. When I run it I get a System.StackOverflowException
and I really cant figure out why... I have reviewed Custom JsonConverter WriteJson Does Not Alter Serialization of Sub-properties and the solution there does not work natively within Newtonsoft and thus ignores all of the Newtonsoft native attributes.
If I pass a single convertor (all the object inherit from IOptions
) I get only the top-level object with the required ObjectType
:
{
"ObjectType": "ProcessorOptionsA",
"ReplayRevisions": true,
"PrefixProjectToNodes": false,
"CollapseRevisions": false,
"WorkItemCreateRetryLimit": 5,
"Enabled": true,
"Endpoints": null,
"ProcessorEnrichers": [
{
"Enabled": true
},
{
"Enabled": true
}
]
}
I have 4 classes that all have my custom OptionsJsonConvertor set as the convertor.
[JsonConverter(typeof(OptionsJsonConvertor<IProcessorEnricherOptions>))]
public interface IProcessorEnricherOptions : IEnricherOptions
{
}
[JsonConverter(typeof(OptionsJsonConvertor<IProcessorOptions>))]
public interface IProcessorOptions : IProcessorConfig, IOptions
{
List<IEndpointOptions> Endpoints { get; set; }
List<IProcessorEnricherOptions> ProcessorEnrichers { get; set; }
IProcessorOptions GetDefault();
}
[JsonConverter(typeof(OptionsJsonConvertor<IEndpointOptions>))]
public interface IEndpointOptions : IOptions
{
[JsonConverter(typeof(StringEnumConverter))]
public EndpointDirection Direction { get; set; }
public List<IEndpointEnricherOptions> EndpointEnrichers { get; set; }
}
[JsonConverter(typeof(OptionsJsonConvertor<IEndpointEnricherOptions>))]
public interface IEndpointEnricherOptions : IEnricherOptions
{
}
The object model does not nest the same object type at any point, but does have List<IEndpointEnricherOptions>
contained within List<IEndpointOptions>
contained within List<IProcessorOptions>
.
"Processors": [
{
"ObjectType": "ProcessorOptionsA",
"Enabled": true,
"ProcessorEnrichers": [
{
"ObjectType": "ProcessorEnricherOptionsA",
"Enabled": true
},
{
"ObjectType": "ProcessorEnricherOptionsB",
"Enabled": true,
}
],
"Endpoints": [
{
"ObjectType": "EndpointOptionsA",
"EndpointEnrichers": [
{
"ObjectType": "EndpointEnricherOptionsA",
"Enabled": true,
}
]
},
{
"ObjectType": "EndpointOptionsA",
"EndpointEnrichers": [
{
"ObjectType": "EndpointEnricherOptionsA",
"Enabled": true,
},
{
"ObjectType": "EndpointEnricherOptionsB",
"Enabled": true,
}
]
}
]
}
]
I want to replicate the TypeNameHandling = TypeNameHandling.Objects
setting but have my own property name as well as finding the objects, but everything else should be the same.
Right now I have public class OptionsJsonConvertor<TOptions> : JsonConverter
which works for a single nested list, but no sub-lists.
public override void WriteJson(JsonWriter writer,object value,JsonSerializer serializer)
{
JToken jt = JToken.FromObject(value);
if (jt.Type != JTokenType.Object)
{
jt.WriteTo(writer);
}
else
{
JObject o = (JObject)jt;
o.AddFirst(new JProperty("ObjectType", value.GetType().Name));
o.WriteTo(writer);
}
}
If I remove all of the [JsonConverter]
class attributes then it executes and adds ObjectType
to the IProcessorOptions
, but not to any of the subtypes. However, with those attributes, I get System.StackOverflowException
on JToken jt = JToken.FromObject(value);
I had thought that this was due to it being the same object type, however even with 4 custom JsonConverter
classes that don't share a common codebase I get the same exception.
I'm stumped and really don't want to have the ugly "$type" = "MyAssmbly.Namespace.Class, Assembly"
node!
UPDATE Even if I only have the OptionsJsonConvertor<IProcessorOptions>
enabled on the Class IProcessorOptions
I get a System.StackOverflowException
.