I recently encountered this kind of problem where I needed to consume an API which has a dynamic data contract, so I developed a package called SerializationInterceptor. Here's the GitHub link: https://github.com/essencebit/SerializationInterceptor/wiki. You can also install the package using Nuget Package Manager.
Example from below uses Newtonsoft.Json for serialization/deserialization. Of course you can use any other tool, as this package does not depend on any.
What you could do is to create an interceptor:
public class JsonPropertyInterceptorAttribute : SerializationInterceptor.Attributes.InterceptorAttribute
{
public JsonPropertyInterceptorAttribute(string interceptorId)
: base(interceptorId, typeof(JsonPropertyAttribute))
{
}
protected override SerializationInterceptor.Attributes.AttributeBuilderParams Intercept(SerializationInterceptor.Attributes.AttributeBuilderParams originalAttributeBuilderParams)
{
object value;
switch (InterceptorId)
{
case "some id":
// For DESERIALIZATION you first need to deserialize the object here having the prop Source unmapped(we'll invoke the proper deserialization later to have Source prop mapped to the correct Json key),
// then get the value of the prop Type and assign it to variable from below.
// For SERIALIZATION you need somehow to have here access to the object you want to serialize and get
// the value of the Type prop and assign it to variable from below.
value = "the value of Type prop";
break;
default:
return originalAttributeBuilderParams;
}
originalAttributeBuilderParams.ConstructorArgs = new[] { value };
return originalAttributeBuilderParams;
}
}
Then place the interceptor on the Source prop:
public class MyRequest
{
[JsonProperty("type")]
public string Type { get; set; }
[JsonPropertyInterceptor("some id")]
[JsonProperty("source")]
public string Source { get; set; }
}
Then you invoke the proper serialization/deserialization like this:
var serializedObj = SerializationInterceptor.Interceptor.InterceptSerialization(obj, objType, (o, t) =>
{
var serializer = new JsonSerializer { ReferenceLoopHandling = ReferenceLoopHandling.Ignore };
using var stream = new MemoryStream();
using var streamWriter = new StreamWriter(stream);
using var jsonTextWriter = new JsonTextWriter(streamWriter);
serializer.Serialize(jsonTextWriter, o, t);
jsonTextWriter.Flush();
return Encoding.Default.GetString(stream.ToArray());
})
var deserializedObj = SerializationInterceptor.Interceptor.InterceptDeserialization(@string, objType, (s, t) =>
{
var serializer = new JsonSerializer();
using var streamReader = new StreamReader(s);
using var jsonTextReader = new JsonTextReader(streamReader);
return serializer.Deserialize(jsonTextReader, t);
});