Reputation: 1809
I have a class Action and many other specific classes that derive from this one like SendCoordinates, MakeCall, etc..
So given a JSON response like this one:
{
"action":{
"type":"SendCoordinates",
"data": "41°24'12.2 N 2°10'26.5"
}
}
Now my question is regarding Newtonsoft json library. What is the best way to implement this ? Should I create specific JSON converters for each class like they show here http://www.newtonsoft.com/json/help/html/DeserializeCustomCreationConverter.htm
Or should I go for a entirelly different aproach that I'm not considering ? Can you guys leave me your opinions on this ? Thanks in advance
Upvotes: 1
Views: 5802
Reputation: 1289
With Newtonsoft.Json you can deserialise to a type via the non-generic overload DeserializeObject(string value, type type)
.
This means you can use the Type
property as a hint to which type to deserialize.
Action
objectSee the following example:
using System;
using Newtonsoft.Json;
namespace com.example.SO42736347
{
public class Action
{
public string Type { get; set; }
}
public class Action1 : Action
{
public string Data { get; set; }
}
public class Program
{
public const string ACTION1 = @"{
""Type"" : ""com.example.Json.Action1"",
""Data"" : ""41°24'12.2 N 2°10'26.5""
}";
public static void Main()
{
var action = JsonConvert.DeserializeObject<Action>(ACTION1);
var type = Type.GetType(action.Type);
var action1 = (Action1) JsonConvert.DeserializeObject(ACTION1, type);
}
}
}
If you do not want to specify the full qualified type name in the Type
field, you can construct the FullName of the type by using custom programme logic (e.g. prefixing it with a base namespace).
Edit: according to the comments it should be able to deserialise a list of actions (of derived types). Therefore I appended the following example to my answer where you can see, how to deserialise a list of actions by doing the following:
Type
of the Action
I also added a loop after the conversion to show how to further process the converted actions.
using System;
using Newtonsoft.Json;
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
namespace com.example.Json
{
public class Action
{
public string Type { get; set; }
}
public class Action1 : Action
{
public string Data { get; set; }
}
public class Action2 : Action
{
public string SomeProperty { get; set; }
}
public class Program
{
public const string ACTION1 = @"{
""Type"" : ""com.example.Json.Action1"",
""Data"" : ""41°24'12.2 N 2°10'26.5""
}";
public const string ACTION2 = @"{
""Type"" : ""com.example.Json.Action2"",
""SomeProperty"" : ""arbitrary-value""
}";
public const string ACTIONS =
"[" +
ACTION1 +
"," +
ACTION2 +
"]" ;
public static void Main()
{
var actions = new List<Action>();
JArray jArray = JArray.Parse(ACTIONS);
foreach(var item in jArray)
{
var json = JsonConvert.SerializeObject(item);
var baseAction = JsonConvert.DeserializeObject<Action>(json);
var type = Type.GetType(baseAction.Type);
var action = (Action) JsonConvert.DeserializeObject(json, type);
actions.Add(action);
}
// now that we have converted all array items into specific derived action objects
// we can start processing them anyway we want
// keep in mind that you have to check the runtime type in order to find out what
// specific kind of action we have
// eg.
foreach(var action in actions)
{
switch(action.Type)
{
case "com.example.Json.Action1":
// do something
Console.WriteLine("found com.example.Json.Action1");
Console.WriteLine((action as Action1).Data);
break;
case "com.example.Json.Action2":
// do something
Console.WriteLine("found com.example.Json.Action2");
Console.WriteLine((action as Action2).SomeProperty);
break;
default:
// do something
Console.WriteLine("found something else");
break;
}
}
}
}
}
Upvotes: 3
Reputation: 3744
You can deserialize it to SomeObject
:
public class SomeObject
{
public SomeAction Action { get; set; }
public OtherAction Call { get; set; }
}
public class SomeAction
{
public string Type { get; set; }
public string Data { get; set; }
}
public class OtherAction { ... }
Possible json
to deserialize:
{
"action":{ "type":"SendCoordinates", "data": "41°24'12.2 N 2°10'26.5" }
}
or:
{
"call":{ ... }
}
Upvotes: 0