We have a microservice developed in C# which needs to integrate with Salesforce.
We are implementing a new instance of Saleforce and for some stupid reason, someone decided to rename one field from My_Field__c
to MyField__c
and they don't want to have any custom fields with any avoidable underscores. Stupid, but not my choice.
Now I need to integrate a new instance of the microservice to the new instance of Salesforce making the solution different by only a single character, but of course we need to be able to maintain both the original microservice and the new microservice.
In an ideal world, I would just set some value in appSettings and consume this in my declaration of [JsonProperty(PropertyName = "My_Field__c")]
, but of course the attribute requires a compile time constant, so we can't do something so simple.
Creating a custom serializer/deserializer or maintaing a different git branch to remove this one character feels like overkill.
Is there some way I can just set this one attribute dynamically?
(TypeDescriptor
was suggested as possibly offering a solution, but I can't find details on how I might apply this.)
I tried to get TypeDescriptor.AddAttributes()
to work with the Type, but this did not work. As the instance would not exist before deserialization, attempting to use it with an instance was a non-starter.
However, I figured out how to make this work with a Contract Resolver:
public static MyModel FromSerializedMyModel(string content, SalesforceFieldNames salesforceFieldNames) =>
JsonConvert.DeserializeObject<MyModel>(contents,
CreateSettings(salesforceFieldNames));
private static JsonSerializerSettings CreateSettings(SalesforceFieldNames salesforceFieldNames) => new()
{
ContractResolver = new MyModelContractResolver(salesforceFieldNames)
};
class MyModelContractResolver: DefaultContractResolver
{
private readonly SalesforceFieldNames _salesforceFieldNames;
public MyModelContractResolver(SalesforceFieldNames salesforceFieldNames) =>
_salesforceFieldNames = salesforceFieldNames;
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization);
Dictionary<string, JsonProperty> propertiesByUnderlyingName = properties.ToDictionary(x => x.UnderlyingName, x => x);
if (propertiesByUnderlyingName.TryGetValue("MyField", out JsonProperty spvTagProperty))
{
spvTagProperty.PropertyName = _salesforceFieldNames.MyField;
}
return properties;
}
}
A bit verbose and otherwise ugly, but it works...