I have JSON data which I want to convert to correct type and then handle it. I'm using MONO and NewtonSoft's JSON library. I.E. JSON and object must match properties 1:1 to convert to right DTO. DTO's have unique properties always.
Both Activator.CreateInstance() and Convert.ChangeType() doesn't seem to compile.
DTOs:
class JSONDTO
{
}
class JSONCommandDTO : JSONDTO
{
public string cmd;
}
class JSONProfileDTO : JSONDTO
{
public string nick;
public string name;
public string email;
}
class JSONMessageDTO : JSONDTO
{
public string msg;
}
Server:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Newtonsoft.Json;
class Server
{
protected static List<JSONDTO> DTOList;
static void Main()
{
DTOList = new List<JSONDTO>();
DTOList.Add(new JSONProfileDTO());
DTOList.Add(new JSONCommandDTO());
DTOList.Add(new JSONMessageDTO());
// ...
}
protected static void OnMessage (string message)
{
dynamic rawObject;
try
{
// Or try to convert to right DTO here somehow?
rawObject = JsonConvert.DeserializeObject<dynamic>(message);
} catch (JsonReaderException ex) {
// Invalid JSON
return;
}
int dtoCount = DTOList.ToArray().Length;
int errCount = 0;
JSONDTO DTOObject;
foreach (var dto in DTOList.ToList()) {
try {
// Doesn't compile:
// DTOObject = Activator.CreateInstance(dto.GetType(), rawObject);
// DTOObject = Convert.ChangeType(rawObject, dto.GetType());
break; // Match found!
} catch (Exception ex) {
// Didn't match
errCount++;
}
}
if (errCount == dtoCount) {
// Right DTO was not found
return;
}
if (DTOObject is JSONProfileDTO) {
AssignProfile((JSONProfileDTO) DTOObject);
}
else if (DTOObject is JSONCommandDTO)
{
RunCommand((JSONCommandDTO) DTOObject);
}
// etc ..
}
protected static void RunCommand (JSONCommandDTO command)
{
string cmd = command.cmd;
Console.WriteLine("command == " + cmd);
}
protected static void AssignProfile(JSONProfileDTO profile)
{
Console.WriteLine("got profile!");
}
}
}
I got it to work. I had to add JsonSerializerSettings with MissingMemberHandling.Error so that exception gets thrown if JSON doesn't fit into object. I was also missing Microsoft.CSharp reference.
class Server
{
protected static List<Type> DTOList = new List<Type>();
static void Main()
{
DTOList.Add(typeof(JSONProfileDTO));
DTOList.Add(typeof(JSONCommandDTO));
DTOList.Add(typeof(JSONMessageDTO));
}
protected static void OnMessage (string rawString)
{
dynamic jsonObject = null;
int DTOCount = DTOList.Count;
int errors = 0;
var settings = new JsonSerializerSettings ();
// This was important
// Now exception is thrown when creating invalid instance in the loop
settings.MissingMemberHandling = MissingMemberHandling.Error;
foreach (Type DTOType in DTOList) {
try {
jsonObject = JsonConvert.DeserializeObject (rawString, DTOType, settings);
break;
} catch (Exception ex) {
errors++;
}
}
if (null == jsonObject) {
return;
}
if (errors == DTOCount) {
return;
}
if (jsonObject is JSONProfileDTO) {
AssignProfile((JSONProfileDTO) jsonObject);
}
else if (jsonObject is JSONCommandDTO)
{
RunCommand((JSONCommandDTO) jsonObject);
}
}
}