I have two components in a distributed system, which send messages which are serialized/deserialized using Newtonsoft.JSON (JSON.Net).
The message properties are currently sent in Norwegian, and I am looking to translate the codebase to English. Since there is a change that some messages would have been sent in Norwegian, and handled by a component which has been upgraded to the English version, it needs to be able to support both.
I would like that on deserialization, both the 'Norwegian' property name as well as English would map to the same property. For example:
For example, take 'name' in English or 'navn' in Norwegian.
public class Message
{
[JsonProperty("Navn")]
public string Name { get; set;}
}
The problem with the above is that it would map only from Navn => Name
. I would like it to map both Navn
and Name
to Name
.
Is this available in Newtonsoft.JSON, without much custom coding?
You could use a custom ContractResolver in this answer:
Json.NET deserialize or serialize json string and map properties to different property names defined at runtime
Or
Use [JsonProperty("")] to look for different variations of the property name and return with one of the properties like this:
public class Message
{
private string _name;
[JsonProperty("Navn" )]
public string NorwegianName { get; set; }
[JsonProperty("Name")]
public string Name {
get { return _name ?? NorwegianName; }
set { _name = value; } }
}
This will return the name with JSON property name: Navn
or Name
.
I had a need to do this and after some experimentation I've found that a resolver that returns multiple JsonProperties for the same MemberInfo is working great. It also serializes with a single specified name but can read from any one name. I'm using this migrate names, its NOT expecting to find more than one of the possible names in the source json.
public class TestClass
{
[FallbackJsonProperty("fn", "firstName", "first_name")]
public string FirstName {get;set;}
}
public class ThingResolver : CamelCasePropertyNamesContractResolver
{
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
var typeMembers = GetSerializableMembers(type);
var properties = new List<JsonProperty>();
foreach (var member in typeMembers)
{
var property = CreateProperty(member, memberSerialization);
properties.Add(property);
var fallbackAttribute = member.GetCustomAttribute<FallbackJsonProperty>();
if (fallbackAttribute == null)
{
continue;
}
property.PropertyName = fallbackAttribute.PreferredName;
foreach (var alternateName in fallbackAttribute.FallbackReadNames)
{
var fallbackProperty = CreateProperty(member, memberSerialization);
fallbackProperty.PropertyName = alternateName;
fallbackProperty.ShouldSerialize = (x) => false;
properties.Add(fallbackProperty);
}
}
return properties;
}
}
[AttributeUsage(AttributeTargets.Property)]
public class FallbackJsonProperty : Attribute
{
public string PreferredName { get; }
public string[] FallbackReadNames { get; }
public FallbackJsonProperty(string preferredName, params string[] fallbackReadNames)
{
PreferredName = preferredName;
FallbackReadNames = fallbackReadNames;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With