I am getting JSon from a third party API which does not match my classes.
Some JSon properties are not be be converted others has different names, etc.
How can I define a custom conversion from the JSON to my C# object.
These are the objects I have in C#:
public class PropertyList {
public Int32 Page { get; set; }
public String[] ErrorMessages { get; set; }
public List<Property> Properties { get; set; }
}
public class Property {
public String Name { get; set; }
public String Reference { get; set; }
public String Region { get; set; }
public IList<String> Features { get; set; }
public String Id { get; set; }
public Double Price { get; set; }
public IList<String> ImagesUrls { get; set; }
}
And this is the JSon data which I want to convert from:
{
"page" : 0,
"errorMessages" : [ ],
"listings" : [
{
"data" : {
"name" : "The name",
"reference__c" : "ref1234",
"region__c" : "London",
"features__c" : "Garage;Garden;",
"id" : "id1234",
"price_pb__c" : 700000,
},
"media" : {
"images" : [
{
"title" : "image1",
"url" : "http://www.domain.com/image1"
},
{
"title" : "image2",
"url" : "http://www.domain.com/image2"
}
]
}
}
{
NOTE: Other items
}
]
}
How should I do this?
UPDATE 1
Using Thiago suggestion I was able to parse Page and ErrorMessages but not Properties. So I create the following converter:
public class PropertyResultConverter : JsonConverter {
public override bool CanConvert(Type objectType) {
return (objectType == typeof(PropertyResult));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
JObject jo = JObject.Load(reader);
PropertyResult propertyResult = jo.ToObject<PropertyResult>();
propertyResult.Properties = jo.SelectToken("listings.data").ToObject<List<Property>>();
return propertyResult;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
throw new NotImplementedException();
}
}
But when I try this I get the following error:
An exception of type 'System.NullReferenceException' occurred
On:
propertyResult.Properties = jo.SelectToken("listings.data").ToObject<List<Property>>();
Any idea why this happens?
Miguel, have you tried http://www.newtonsoft.com/json ?
You can do the mappings of your code using C# attributes, like the snippets below.
public class PropertyList {
[JsonProperty("page")]
public Int32 Page { get; set; }
[JsonProperty("errorMessages")]
public String[] ErrorMessages { get; set; }
[JsonProperty("listings")]
public List<Property> Properties { get; set; }
}
public class Property {
[JsonProperty("name")]
public String Name { get; set; }
[JsonProperty("reference__c")]
public String Reference { get; set; }
[JsonProperty("region__c")]
public String Region { get; set; }
[JsonProperty("features__c")]
public IList<String> Features { get; set; }
[JsonProperty("id")]
public String Id { get; set; }
[JsonProperty("price_pb__c")]
public Double Price { get; set; }
[JsonProperty("media")]
public IList<String> ImagesUrls { get; set; }
}
I'm not sure if IList will work as you are expecting. I believe you will need to adapt it to Dictionary.
You can take a look on the API:
http://www.newtonsoft.com/json/help/html/SerializationAttributes.htm
UPDATE
Try to parse 'data' using the snippet below:
JObject jsonObject = JObject.Parse(json);
IList<JToken> results = jsonObject["listings"]["data"].Children().ToList();
IList<Property> processedList = new List<Property>();
foreach (JToken item in results)
{
Property propertyItem = JsonConvert.DeserializeObject<Property>(item.ToString());
processedList.Add(propertyItem);
}
I ran that snippet and it worked. You can explore the code that I generated on my github:
https://github.com/thiagoavelino/VisualStudio_C/blob/master/VisualStudio_C/StackOverFlow/ParsingJason/ParsingJson.cs
Related
I have this incoming request with this payload
{
count : 10,
supplier : {
id : 342,
name : 'test'
},
title : 'some title'
}
and I have this model in my c# code
class SomeModel
{
public string Title { get; set; }
public int SupplierId { get; set; }
public double Amount { get; set; }
}
This is my controller method
public IActionResult Foo(SomeModel data)
{
//...
}
I would like to map the property count in request payload to Amount property in my c# model and mapping the value of supplier.id into SupplierId.
I'm using Newtonsoft Json.NET library for binding
Obviously the simplest way is to create a class corresponding to payload stucture like this
public class SomeModel
{
public string Title { get; set; }
public double Count { get; set; }
public Supplier Supplier { get; set; }
}
public class Supplier
{
public int Id { get; set; }
public string Name { get; set; }
}
Another iteration could be using JsonProperty attribute for Amount and SupplierId property making use of Supplier
class SomeModel
{
public string Title { get; set; }
[JsonProperty("count")]
public double Amount { get; set; }
public int SupplierId => Supplier.Id;
public Supplier Supplier { get; set; }
}
class Supplier
{
public int Id { get; set; }
public string Name { get; set; }
}
But if you like to stick with your current model you will need to create a custom converter. And what I can suggest you
public class NestedPropertyConverter : JsonConverter
{
private string[] _properties;
public NestedPropertyConverter(string propertyChain)
{
//todo: check if property chain has valid structure
_properties = propertyChain.Split('.');
}
public override bool CanWrite => false;
public override bool CanConvert(Type objectType) => true;
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JToken token = (JToken)serializer.Deserialize(reader);
foreach (string property in _properties)
{
token = token[property];
if (token == null) //if property doesn't exist
return existingValue; //or throw exception
}
return token.ToObject(objectType);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
Basically, the converter allows to bind nested properties. Usage
class SomeModel
{
public string Title { get; set; }
[JsonConverter(typeof(NestedPropertyConverter), "id")]
[JsonProperty("supplier")] //its necessary to specify top level property name
public int SupplierId { get; set; }
[JsonProperty("count")]
public double Amount { get; set; }
}
Note
I also tested the following payload
{
count : 10,
supplier : {
id : 342,
name : "test",
test: {
val: 55
}
},
title : "some title"
}
and config for property
[JsonConverter(typeof(NestedPropertyConverter), "test.val")]
[JsonProperty("supplier")]
public int SupplierId { get; set; }
and it works fine.
I have a 3rdParty program that I receive JOSN data from. The Json can come in two ways and I have created two classes to represent the two JSON messages using http://json2csharp.com/
public class Data1
{
public Content1 content { get; set; }
public string name { get; set; }
public string address { get; set; }
public string age { get; set; }
}
public class Data2
{
public Content2 content { get; set; }
public string name { get; set; }
public string address { get; set; }
public string age { get; set; }
}
They are the same apart from Content1 and Content2 (I have classes for them also).
I want to deserialize the data like so:
var object1 = JsonConvert.DeserializeObject<Data1>(message1);
var object2 = JsonConvert.DeserializeObject<Data2>(message2);
But I do not know what message I will receive so how can I create one class that I can deserialize to and then use.
I have looked at this example https://www.jerriepelser.com/blog/deserialize-different-json-object-same-class/ and have attempted to create a SuperClass that has a:
[JsonConverter(typeof(SuperData))]
but I'm not sure how to implement the ReadJson function.
Do I check the data that comes in and detect if content is type Content1 or Content2? If so how do I do this?
How do I then know what class has been deserialized so I can then know to check for the different content?
Here is the json:
Data1
{
"content": {
"person_id": "1234",
"timestamp": "2018-10-30 13:09:04.382885",
"features": "old, cranky"
},
"name": "JoeBloggs",
"address": "address1",
"age": 31,
}
Data2
{
"content":
{
"detections": 1,
"detection_boxes": [
{
"name": "JoeBloggs",
"bbox": [
1988.162842886987,
-20.466329557695307,
2662.417876180017,
846.0808020362452
],
"id": 3610
}
],
"timestamp": "2018-10-30 13:09:07.171000",
]
},
"name": "JoeBloggs",
"address": "address1",
"age": 31,
}
I have tried this:
[JsonConverter(typeof(MyDataConverter))]
public class MegaData
{
public object content { get; set; }
public string name { get; set; }
public string address { get; set; }
public string age { get; set; }
}
MyDataConverter has the following:
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var jObject = JObject.Load(reader);
var content = jObject["message_content"];
if (content["person_id"] != null)
{
return jObject.ToObject<Data1>();
}
else
{
return jObject.ToObject<Data2>();
}
}
Then I attempt to deserialize it as follows:
var alert = JsonConvert.DeserializeObject<MegaData>(message1); <-- EXCEPTION
**Unable to cast object of type 'Data1' to type 'MegaData'.**
What should my MegaData class look like for this to work??
Why can't you have a single class with both type and deserialize to that like
public class DetectionBox
{
public string name { get; set; }
public List<double> bbox { get; set; }
public int id { get; set; }
}
public class Content
{
public int detections { get; set; }
public List<DetectionBox> detection_boxes { get; set; }
public string timestamp { get; set; }
public string person_id { get; set; }
public string features { get; set; }
}
public class Data
{
public Content content { get; set; }
public string name { get; set; }
public string address { get; set; }
public int age { get; set; }
}
Data data = JsonConvert.DeserializeObject<Data>(json);
So you can create a custom converter derived from JsonConverter and in the ReadJson you'd do something like this:
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var jObject = JObject.Load(reader);
var content = jObject["content"];
if (content["person_id"] != null)
{
return jObject.ToObject<Data1>();
}
else
{
return jObject.ToObject<Data2>();
}
}
If you aren't actually writing JSON, you can skip the WriteJson (have it throw a NotImplementedException) method and set CanWrite to return false (so it won't ever be called anyway).
I have this class hierarchy :
public class ProxyBotsSnapshotLogEntryDetails : IBotsSnapshotLogEntryDetails
{
public ICollection<IBotSnapshot> Snapshots { get; set; }
}
public class ProxyBotSnapshot : IBotSnapshot
{
public string Name { get; set; }
public ICollection<IBotSnapshotItem> States { get; set; }
}
public class ProxyBotSnapshotItem : IBotSnapshotItem
{
public int Count { get; set; }
public IrcBotChannelStateEnum State { get; set; }
}
and their corresponding interfaces
public interface IBotsSnapshotLogEntryDetails
{
ICollection<IBotSnapshot> Snapshots { get; set; }
}
public interface IBotSnapshot
{
string Name { get; set; }
ICollection<IBotSnapshotItem> States { get; set; }
}
public interface IBotSnapshotItem
{
int Count { get; set; }
IrcBotChannelStateEnum State { get; set; }
}
that I would like to deserialize from JSON:
var test = JsonConvert.DeserializeObject<ProxyBotsSnapshotLogEntryDetails>(entry.DetailsSerialized);
but I get an error saying that Newtonsoft cannot convert interfaces.
I found this promising article:
https://www.c-sharpcorner.com/UploadFile/20c06b/deserializing-interface-properties-with-json-net/
but am not sure how to use the attribute, since in my case, the property is a list of interface.
The converter provided in the article works super nicely, I was just missing the syntax to use it on a collection property. Here is the code with the converter and the working attributes:
// From the article
public class ConcreteConverter<T> : JsonConverter
{
public override bool CanConvert(Type objectType) => true;
public override object ReadJson(JsonReader reader,
Type objectType, object existingValue, JsonSerializer serializer)
{
return serializer.Deserialize<T>(reader);
}
public override void WriteJson(JsonWriter writer,
object value, JsonSerializer serializer)
{
serializer.Serialize(writer, value);
}
}
public class ProxyBotsSnapshotLogEntryDetails : IBotsSnapshotLogEntryDetails
{
[JsonProperty(ItemConverterType = typeof(ConcreteConverter<ProxyBotSnapshot>))]
public ICollection<IBotSnapshot> Snapshots { get; set; }
}
public class ProxyBotSnapshot : IBotSnapshot
{
public string Name { get; set; }
[JsonProperty(ItemConverterType = typeof(ConcreteConverter<ProxyBotSnapshotItem>))]
public ICollection<IBotSnapshotItem> States { get; set; }
}
public class ProxyBotSnapshotItem : IBotSnapshotItem
{
public int Count { get; set; }
public IrcBotChannelStateEnum State { get; set; }
}
Maybe it works if you add the following settings to the Serializer and Deserializer methods:
new JsonSerializerSettings {TypeNameHandling = TypeNameHandling.Auto}
For example:
var test = JsonConvert.DeserializeObject<ProxyBotsSnapshotLogEntryDetails>(entry.DetailsSerialized,
new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
});
This is probably something really simple and I looked everywhere and tried everything I could come up with. So I apologize if this is a simple search and I was just looking for the wrong thing. I'm also new to data contracts and somewhat JSON so this probably isn't really that complex.
I am creating an API to ingest JSON and store it in our database.
The JSON will look something like this:
{
"appname" : "MyApp",
"key" : "Test123",
"data" :[
{ "data1" : "10551296", "data2" : "TrainingIns", "data3" : "Completed"}
,
{ "connectorType" : "webserver-to-appserver", "sourceUri" : "data4", "destinationUri" : "data5", "rails" : "N", "data6" : "null" }
,
{ "groupId" : "group1", "failbackAction" : "null", "normal" : "null", "failoverAction" : "null", "failbackAction" : "null", "failoverAction" : "null", "artifactId" : "mywebserver", "normalState" : "null" }
,
{ "instanceId" : "10551296abc" }]
,
"updateId" : "MyID",
"updateTS" : "30-AUG-16 05.56.24.000000000 AM" ,
"creationUser" : "APICall"
}
Where the 'data' field will be an array with a variable amount of JSON objects. The issue I am having stems from either not getting data in the 'data' object or having it be completely undefined.
[DataContract]
public class Update_DB
{
[DataMember(Name = "appname", IsRequired = true)]
public string appname { get; set; }
[DataMember]
public string key { get; set; }
[DataMember(Name="data",IsRequired = true)]
public List<JsonValue> data { get; set; }
[DataMember]
public string updateId { get; set; }
[DataMember]
public string updateTS { get; set; }
[DataMember]
public string creationUser { get; set; }
}
I've gathered I might need a collection of some sort? I've tried everything I could find but I don't know how I should define the data member for 'data'.
The above contract gives me empty arrays when I do this:
string x = JsonConvert.SerializeObject(collection.data);
I can get every other field I just need to turn the 'data' field into a string.
Hopefully that is enough info. Thanks in advance for any help!
Under normal circumstances, you could define your data property as a List<Dictionary<string, string>>, like so:
[DataMember(Name = "data", IsRequired = true)]
public List<Dictionary<string, string>> data { get; set; }
Then you would be able to serialize and deserialize it successfully with Json.NET. Unfortunately, one of your data objects has duplicated keys:
{
"groupId":"group1",
"failbackAction":"null",
"normal":"null",
"failoverAction":"null",
"failbackAction":"null",
"failoverAction":"null",
"artifactId":"mywebserver",
"normalState":"null"
},
Using duplicated keys is not recommended by the JSON standard, which states:
When the names within an object are not unique, the behavior of software that receives such an object is unpredictable.
In addition, c# dictionaries of course do not support duplicated keys, and data contract serialization does not duplicated property names.
However, it is possible to read a JSON object with duplicated keys using Json.NET's JsonReader and create a custom JsonConverter to handle duplicated keys.
First, define the following class to replace JsonValue. JsonValue is a silverlight-specific class whose use has been deprecated in overall .Net:
[JsonConverter(typeof(JsonValueListConverter))]
public sealed class JsonValueList
{
public JsonValueList()
{
this.Values = new List<KeyValuePair<string, string>>();
}
public List<KeyValuePair<string, string>> Values { get; private set; }
}
class JsonValueListConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(JsonValueList).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var jsonValue = (existingValue as JsonValueList ?? new JsonValueList());
if (reader.TokenType != JsonToken.StartObject)
throw new JsonSerializationException("Invalid reader.TokenType " + reader.TokenType);
while (reader.Read())
{
switch (reader.TokenType)
{
case JsonToken.Comment:
break;
case JsonToken.PropertyName:
{
var key = reader.Value.ToString();
if (!reader.Read())
throw new JsonSerializationException(string.Format("Missing value at path: {0}", reader.Path));
var value = serializer.Deserialize<string>(reader);
jsonValue.Values.Add(new KeyValuePair<string, string>(key, value));
}
break;
case JsonToken.EndObject:
return jsonValue;
default:
throw new JsonSerializationException(string.Format("Unknown token {0} at path: {1} ", reader.TokenType, reader.Path));
}
}
throw new JsonSerializationException(string.Format("Unclosed object at path: {0}", reader.Path));
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var jsonValue = (JsonValueList)value;
writer.WriteStartObject();
foreach (var pair in jsonValue.Values)
{
writer.WritePropertyName(pair.Key);
writer.WriteValue(pair.Value);
}
writer.WriteEndObject();
}
}
Notice the use of [JsonConverter(typeof(JsonValueListConverter))]. This specifies the use of a custom converter when serializing and deserializing JsonValueList.
Next, define your Update_DB class as follows:
[DataContract]
public class Update_DB
{
[DataMember(Name = "appname", IsRequired = true)]
public string appname { get; set; }
[DataMember]
public string key { get; set; }
[DataMember(Name = "data", IsRequired = true)]
public List<JsonValueList> data { get; set; }
[DataMember]
public string updateId { get; set; }
[DataMember]
public string updateTS { get; set; }
[DataMember]
public string creationUser { get; set; }
}
Now you will be able to serialize and deserialize your JSON successfully. Sample fiddle.
Update
If you do not have duplicated keys, you can define your class as follows:
[DataContract]
public class Update_DB
{
[DataMember(Name = "appname", IsRequired = true)]
public string appname { get; set; }
[DataMember]
public string key { get; set; }
[DataMember(Name = "data", IsRequired = true)]
public List<Dictionary<string, string>> data { get; set; }
[DataMember]
public string updateId { get; set; }
[DataMember]
public string updateTS { get; set; }
[DataMember]
public string creationUser { get; set; }
}
And then the following:
var collection = new Update_DB
{
data = new List<Dictionary<string, string>>
{
new Dictionary<string, string>
{
{"data1", "10551296"},
{"data2", "TrainingIns"},
{"data3", "Completed"},
},
new Dictionary<string, string>
{
{"connectorType", "webserver-to-appserver"},
{"sourceUri", "data4"},
{"destinationUri", "data5"},
},
},
};
string x = JsonConvert.SerializeObject(collection.data, Formatting.Indented);
Console.WriteLine(x);
Produces the output:
[
{
"data1": "10551296",
"data2": "TrainingIns",
"data3": "Completed"
},
{
"connectorType": "webserver-to-appserver",
"sourceUri": "data4",
"destinationUri": "data5"
}
]
Sample fiddle.
Another option is to use the dynamic keyword. You could use a list of this type for data (per below).
[DataContract]
public class Update_DB
{
[DataMember(Name = "appname", IsRequired = true)]
public string appname { get; set; }
[DataMember]
public string key { get; set; }
[DataMember(Name = "data", IsRequired = true)]
public List<dynamic> data { get; set; }
[DataMember]
public string updateId { get; set; }
[DataMember]
public string updateTS { get; set; }
[DataMember]
public string creationUser { get; set; }
}
From there, you could use the object by deserializing with JSON.Net, and access into the dynamic data object (assuming you know something about the shape of this dynamic object). Something like below will work based on the input string from the original post.
Update_DB dataObj = JsonConvert.DeserializeObject<Update_DB>(objectJSON);
string test = dataObj.data[1].connectorType; //evaluates to "webserver-to-appserver"
Use Json2CSharp.com to make sure you have everything correct:
public class Datum
{
public string data1 { get; set; }
public string data2 { get; set; }
public string data3 { get; set; }
public string connectorType { get; set; }
public string sourceUri { get; set; }
public string destinationUri { get; set; }
public string rails { get; set; }
public string data6 { get; set; }
public string groupId { get; set; }
public string failbackAction { get; set; }
public string normal { get; set; }
public string failoverAction { get; set; }
public string artifactId { get; set; }
public string normalState { get; set; }
public string instanceId { get; set; }
}
public class RootObject
{
public string appname { get; set; }
public string key { get; set; }
public List<Datum> data { get; set; }
public string updateId { get; set; }
public string updateTS { get; set; }
public string creationUser { get; set; }
}
Over the last few days I have been researching on how to deserialize a JSON response to and C# object. The JSON is valid but I can not get any JSON to C# converters to convert it. I also cannot find an answer on Stackoverflow that works for this instance.
The JSON Response is:
[
{
"SEX": "Male",
"BREED": "Opifex",
"PVPRATING": 1301,
"NAME": "Kilmanagh",
"FIRSTNAME": "Big",
"PVPTITLE": "Freshman",
"LASTNAME": "Kahuna",
"CHAR_DIMENSION": 5,
"ALIENLEVEL": 30,
"RANK_name": "Vindicator",
"HEADID": 40281,
"PROFNAME": "Guru",
"LEVELX": 220,
"PROF": "Martial Artist",
"CHAR_INSTANCE": 12734,
"SIDE": "Omni"
},
{
"ORG_DIMENSION": 5,
"RANK_TITLE": "President",
"ORG_INSTANCE": 9911,
"NAME": "Elements of Destruction",
"RANK": 0
},
"2016/04/06 08:37:26"
]
From my inspection it is an array that contains two objects and a string.
I have used the following to attempt to convert it to an object:
resultArray = JsonConvert.DeserializeObject<List<JsonWhoisResult>>(data);
and
result = JsonConvert.DeserializeObject<JsonWhoisResult>(data);
Either way I get an error:
Error converting value ...(snip)... [ConsoleApplication6.JsonWhoisResult]'. Path '', line 1, position 536.`
I do not know if I have the object wrong, or if I am using incorrect code for this JSON format. I am using:
public class JsonWhoisResult
{
public stats stats { get; set; }
public header header { get; set; }
public string datetime { get; set; }
}
public class header
{
public int ORG_DIMENSION { get; set; }
public string RANK_TITLE { get; set; }
public int ORG_INSTANCE { get; set; }
public string NAME { get; set; }
public int RANK { get; set; }
}
public class stats
{
public string SEX { get; set; }
public string BREED { get; set; }
public int PVPRATING { get; set; }
public string NAME { get; set; }
public string FIRSTNAME { get; set; }
public string PVPTITLE { get; set; }
public string LASTNAME { get; set; }
public int CHAR_DIMENSION { get; set; }
public int ALIENLEVEL { get; set; }
public string RANK_name { get; set; }
public int HEADID { get; set; }
public string PROFNAME { get; set; }
public int LEVELX { get; set; }
public string PROF { get; set; }
public int CHAR_INSTANCE { get; set; }
public string SIDE { get; set; }
}
If anyone has any solutions I would really appreciate it. I have several more that use this type of style. If I can get a solution then I should be able to apply it to the rest.
Because your JSON is an array you cannot deserialize into a single JsonWhoisResult, and because your array contains disparate object types, you cannot deserialize directly into a List<JsonWhoisResult>. You will need to make a custom JsonConverter to handle this situation. The converter can use Json.Net's LINQ-to-JSON API to deserialize the JSON, then manually extract each item into its appropriate object type and populate a single JsonWhoisResult as you want. Something like this should work:
class JsonWhoisResultConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(JsonWhoisResult));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JArray array = JArray.Load(reader);
JsonWhoisResult result = new JsonWhoisResult();
result.stats = array[0].ToObject<stats>();
result.header = array[1].ToObject<header>();
result.datetime = array[2].ToString();
return result;
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
Then use it like this:
JsonWhoisResult result = JsonConvert.DeserializeObject<JsonWhoisResult>(json, new JsonWhoisResultConverter());
Fiddle: https://dotnetfiddle.net/d1hkCn
You can use JSON.net's support for dynamic to do this. I just tested this with the JSON as you pasted it above, and it works - but note, this is not strongly typed.
dynamic result = JsonConvert.DeserializeObject(json);
// value is "Freshman"
Console.WriteLine("result[0].PVPTITLE = '{0}'", result[0].PVPTITLE);
// value is "President"
Console.WriteLine("result[1].RANK_TITLE = '{0}'", result[1].RANK_TITLE);
// value is 2016-04-06 08:37:27
Console.WriteLine("result[2] '{0}'", (DateTime)result[2]);