Reputation: 87
I have a specific situation where I need to include the class name as property in JSON when classes are serialized. The tricky parts is I need to do this dynamically. I can't just create an anonymous class before calling serialization.
I have decorated my class with a custom attribute as below:
[OntologyArea("con", " http://someurl/area/DomicileAddress")]
public class DomicileAddress : IContactPoint
{
[JsonProperty(PropertyName = "con:hasAddressPoint")]
public IAddressPoint AddressPoint
{
get; set;
}
}
In the above example the OntologyArea
attribute should be read and included as a Property. The propery name should be the first argument of OntologyArea
+ the class name (i.e con:DomicileAddress) and the value should be the concrete class of IAddressPoint
.
The tricky part is that the concrete class of IAddressPoint might need to do the same as shown here:
[OntologyArea("geo", "http://someurl.net/geolocation")]
public class StreetAddress : IAddressPoint
{
[JsonProperty("geo:hasStartingStreetNumber")]
public string StartingStreetNumber
{
get; set;
}
}
an example of JSON:
"con:DomicileAddress" : {
"con:hasAddressPoint" : {
"geo:StreetAddress" : {
"geo:hasEndingStreetNumber" : ""
}
}
}
So if any object does have a OntologyArea
attribute I need to add a parent level. If it does not contain this attribute normal serilization should continue.
Please let me know If I need to explain more.
Upvotes: 1
Views: 6837
Reputation: 87
This pointed me in the correct direction. I have an attribute that is read in this class and appended to the writer object.
Upvotes: 0
Reputation: 18013
Is this solution for specifying the concrete type is a must or is it just your proposed solution?
Because Json.NET has a built-in support for encoding the actual types for properties of interface types or base classes:
var json = JsonConvert.SerializeObject(myContract, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto });
If you really need a completely custom logic you have to implement a converter, which also can be passed to the JsonSerializerSettings
. It must be derived from JsonConverter
and you have to implement the WriteJson
method to emit your desired json sting using low level tokens just like in case of an XmlWriter
:
private class MyConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(IAddressPoint).IsAssignableFrom(objectType);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var address = (IAddressPoint)value;
writer.WriteStartObject(); // {
writer.WritePropertyName($"geo:{address.GetType().Name}"); // "geo:StreetAddress"
// ... etc.
writer.WriteEndObject(); // }
// or you can just emit raw string:
writer.WriteRaw(myJsonBody);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
{
// todo: and the deserialization part goes here
}
}
Upvotes: 1