When you serialize an object with Newtonsoft's Json.NET it will resolve the serialization contract for the type being serialized. This means that if you want to serialize an object so that it matches one of the interfaces that it implements you will need to use a customized contract resolver.
When I first tried to do this I made a completely custom JsonConverter for the type that looked up the properties via reflection and just wrote their values out manually. Unfortunately had the side effect of bypassing all of the features the Newtonsoft provides with regard to decorating classes and customizing the serialization process for that object.
There was a good topic on Stack Overflow about this that led me to the custom contract resolver solution. However the sample implementation there is hard coded to only try to serialize one hard coded type for all serialization.
Below is an implementation (with tests) that allows you to specify a list of interfaces that you want to serialize by, and then if the object being serialized does implement that interface it will fall back on it's default contract.
InterfaceContractResolver Implementation
public class InterfaceContractResolver : DefaultContractResolver
{
private readonly Type[] _interfaceTypes;
private readonly ConcurrentDictionary<Type, Type> _typeToSerializeMap;
public InterfaceContractResolver(params Type[] interfaceTypes)
{
_interfaceTypes = interfaceTypes;
_typeToSerializeMap = new ConcurrentDictionary<Type, Type>();
}
protected override IList<JsonProperty> CreateProperties(
Type type,
MemberSerialization memberSerialization)
{
var typeToSerialize = _typeToSerializeMap.GetOrAdd(
type,
t => _interfaceTypes.FirstOrDefault(
it => it.IsAssignableFrom(t)) ?? t);
return base.CreateProperties(typeToSerialize, memberSerialization);
}
}
Unit Tests
public interface ISample
{
int Id { get; }
IList<string> Names { get; }
}
public class Sample : ISample
{
int ISample.Id
{
get { return Identity; }
}
public int Identity { get; set; }
public IList<string> Names { get; set; }
public bool IsValid { get; set; }
}
public class Example
{
public int Id { get; set; }
public string Names { get; set; }
public bool IsTrue { get; set; }
}
public class InterfaceContractResolverTests
{
[Fact]
public void SerializeSample()
{
var settings = new JsonSerializerSettings
{
ContractResolver = new InterfaceContractResolver(typeof (ISample))
};
var sample = new Sample
{
Identity = 42,
IsValid = true,
Names = new[] {"Linq", "Sql"}
};
var sampleJson1 = JsonConvert.SerializeObject(sample);
var sampleJson2 = JsonConvert.SerializeObject(sample, settings);
Assert.Equal(
@"{""Identity"":42,""Names"":[""Linq"",""Sql""],""IsValid"":true}",
sampleJson1);
Assert.Equal(
@"{""Id"":42,""Names"":[""Linq"",""Sql""]}",
sampleJson2);
}
[Fact]
public void SerializeExample()
{
var settings = new JsonSerializerSettings
{
ContractResolver = new InterfaceContractResolver(typeof (ISample))
};
var example = new Example
{
Id = 2,
Names = "Hello World",
IsTrue = false
};
var exampleJson1 = JsonConvert.SerializeObject(example);
var exampleJson2 = JsonConvert.SerializeObject(example, settings);
Assert.Equal(
@"{""Id"":2,""Names"":""Hello World"",""IsTrue"":false}",
exampleJson1);
Assert.Equal(exampleJson1, exampleJson2);
}
}
Enjoy,
Tom
This solution doesn't seem to work, at least with the current version of NewtonSoft.Json. I've found out that the properties in the interface are being ignored by default. If you replace the last line of CreateProperties with this, it solves the issue:
ReplyDeletevar props = base.CreateProperties(typeToSerialize, memberSerialization);
foreach(var prop in props)
{
prop.Ignored = false;
}
return props;
Thanks for letting me know. I would like to go back and update this for .NET Core; if I do, then I will make sure to post a link here to the updated version.
Deletegreat
ReplyDeleteImportance of community and the suffering economy becoming front of mind for many people today, the local market offers a place for residents to contribute directly to individuals and organizations for whom local production is paramount. The number one priority of a local market is to offer things that are homemade, handmade and homegrown. whitley residences
ReplyDeleteThere are also strict laws in place to protect buyers and investors. A country which places emphasis on protecting investors will always attract investments. For property investment, there are heavy restrictions to protect people's money in the Singapore property market. nim collection
ReplyDeleteI was surfing net and fortunately came across this site and found very interesting stuff here. Its really fun to read. I enjoyed a lot. Thanks for sharing this wonderful information. el gouna white villas for sale
ReplyDeleteBuilding monetary models is a workmanship. The best way to further develop your specialty is to construct an assortment of monetary models across various businesses. We should attempt a model for a venture that isn't past the range of most people - a speculation property.
ReplyDeleteStump Removal Stockton
We should likewise pull the claimed property estimation line from the property tab (denoting the qualities in green to show that they come from an alternate sheet). nova city developers islamabad
ReplyDeleteThe cutting of the storage compartment into the few areas that would then be able to be brought down with a controlled crane activity is additionally significant for the tight situation that might be available. Tree Trimming team Syracuse
ReplyDeleteSo, can a simple layman person operate on a surgical table? No, right? An inexperienced and uncertified person cannot just use an axe or chainsaw to cut a tree. Albuquerque Tree Pruning
ReplyDeleteA great deal of American administration organizations get their payoffs from the help merchants who are continually conveyed to the properties. plot for sale in university town islamabad
ReplyDeleteYour expense of conveyance will likely be at least 5 pennies for each flyer under a specific conveyance sum (say 30,000).point loma homes for sale
ReplyDeleteTajarat strives to be Pakistan's biggest real estate developer ever, guaranteeing the highest international standards, prompt execution, and lifetime customer loyalty. For further detail visit lahore smart city payment plan
ReplyDeleteAs a component of this interaction, it is insightful to incorporate adjoining properties and examine them to guarantee that they affect your subject property. real estate Nigeria
ReplyDeleteThanks for providing recent updates regarding the concern, I look forward to read more. New lenox real estate agents
ReplyDeleteI wanted to thank you for this excellent read!! I definitely loved every little bit of it. I have you bookmarked your site to check out the new stuff you post. وصلت
ReplyDeleteYou made some good points there. I did a Google search about the topic and found most people will believe your blog. Feel free to visit my website; 바카라사이트
ReplyDeleteHi there! Nice post! Please tell us when I will see a follow up! 0
ReplyDelete릴게임
포커게임
We should likewise pull the possessed property estimation line from the property tab.
ReplyDeletecash home buyers Philadelphia
The property estimation line will just extend the worth of the property over the long run.
ReplyDeletehttps://districtrealty.com/
No big surprise, the Web has made nearby real estate a worldwide business. completerealestatepros
ReplyDelete