So I'm making a small JSON Parser.
This is the JSON I want to parse:
{"158023":{"prices":{"xbox":{"LCPrice":"225,000","LCPrice2":"232,000","LCPrice3":"235,000","LCPrice4":"235,000","LCPrice5":"239,000","updated":"15 secs ago","MinPrice":"27,000","MaxPrice":"500,000","PRP":"41"},"ps":{"LCPrice":"228,000","LCPrice2":"231,000","LCPrice3":"232,000","LCPrice4":"233,000","LCPrice5":"235,000","updated":"9 mins ago","MinPrice":"30,000","MaxPrice":"550,000","PRP":"38"},"pc":{"LCPrice":"305,000","LCPrice2":"305,000","LCPrice3":"315,000","LCPrice4":"333,000","LCPrice5":"347,000","updated":"1 hour ago","MinPrice":"37,000","MaxPrice":"700,000","PRP":"40"}}}}
And I have the following class, to represent the Json Object.
public partial class Prices
{
[JsonProperty("158023")]
public Token TokenNumber { get; set; }
}
public partial class Token
{
[JsonProperty("prices")]
public PricesClass Prices { get; set; }
}
public partial class PricesClass
{
[JsonProperty("xbox")]
public Pc Xbox { get; set; }
[JsonProperty("ps")]
public Pc Ps { get; set; }
[JsonProperty("pc")]
public Pc Pc { get; set; }
}
public partial class Pc
{
[JsonProperty("LCPrice")]
public string LcPrice { get; set; }
[JsonProperty("LCPrice2")]
public string LcPrice2 { get; set; }
[JsonProperty("LCPrice3")]
public string LcPrice3 { get; set; }
[JsonProperty("LCPrice4")]
public string LcPrice4 { get; set; }
[JsonProperty("LCPrice5")]
public string LcPrice5 { get; set; }
[JsonProperty("updated")]
public string Updated { get; set; }
[JsonProperty("MinPrice")]
public string MinPrice { get; set; }
[JsonProperty("MaxPrice")]
public string MaxPrice { get; set; }
[JsonProperty("PRP")]
public string Prp { get; set; }
}
public partial class Prices
{
public static Prices FromJson(string json) => JsonConvert.DeserializeObject<Prices>(json, PriceConverter.Settings);
}
internal static class PriceConverter
{
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
{
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
DateParseHandling = DateParseHandling.None,
Converters = {
new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
},
};
}
I'm easily able to parse the JSON, by doing:
Prices prices = Prices.FromJson(myJson);
The problem is when I want to use a different number than 158023.
For example, 158025.
The JsonProperty on the Prices class is already set to "158023", and I have no clue how to rename it.
TLDR:
I have a JSON Object, which I want to rename the JsonProperty text, before deserializing.
Since you don't know the key, use a Dictionary<string, Token> instead of the property TokenNumber in class Prices.
public partial class Prices
{
// Remove this property
// [JsonProperty("158023")]
// public Token TokenNumber { get; set; }
}
public partial class Prices
{
public static Dictionary<string, Token> FromJson(string json) => JsonConvert.DeserializeObject<Dictionary<string, Token>>(json, PriceConverter.Settings);
}
Now the result will be a dictionary where the key is the token value as an string and the value is a Token object.
You could make use of the JsonExtensionData and OnDeserialized attributes:
public class Wrapper
{
public string Id { get; set; }
public Item Item { get; set; }
[JsonExtensionData]
private IDictionary<string, JToken> _additionalData;
[OnDeserialized]
private void OnDeserialized(StreamingContext context)
{
// Get the first key. If you have more than one, you may need
// to customize this for your use case
var id = _additionalData.Keys.FirstOrDefault();
if (id != null)
{
// Assign to our Id property
this.Id = id;
// Create a reader for the subobject
var itemReader = _additionalData[id].CreateReader();
var serializer = new JsonSerializer();
// Deserialize the subobject into our Item property
this.Item = serializer.Deserialize<Item>(itemReader);
itemReader.Close();
}
}
}
public class Item
{
public string Name { get; set; }
}
You can try it here. Alternatively you could write a JsonConverter to achieve the same thing, or do what Amir suggested.
Related
I don't know if there is an existing name for that case, but I'm trying to retrieve data from NASA API (https://api.nasa.gov/) and I have a simple challenge to catch a list of objects near earth. Here is the JSON response I have from the GET request I do to "https://api.nasa.gov/neo/rest/v1/feed?...."
{
"links": {
"next": "http://www.neowsapp.com/rest/v1/feed?start_date=2021-07-04&end_date=2021-07-04&detailed=false&api_key=NjgpxgSbYHXyFSBI3HaOhRowtjMZgAKv2t4DMRym",
"prev": "http://www.neowsapp.com/rest/v1/feed?start_date=2021-07-02&end_date=2021-07-02&detailed=false&api_key=NjgpxgSbYHXyFSBI3HaOhRowtjMZgAKv2t4DMRym",
"self": "http://www.neowsapp.com/rest/v1/feed?start_date=2021-07-03&end_date=2021-07-03&detailed=false&api_key=NjgpxgSbYHXyFSBI3HaOhRowtjMZgAKv2t4DMRym"
},
"element_count": 6,
"near_earth_objects": {
"2021-07-03": [
{
"links": {
"self": "http://www.neowsapp.com/rest/v1/neo/3701710?api_key=NjgpxgSbYHXyFSBI3HaOhRowtjMZgAKv2t4DMRym"
},
"id": "3701710",
"neo_reference_id": "3701710",
"name": "(2014 WF497)",
"nasa_jpl_url": "http://ssd.jpl.nasa.gov/sbdb.cgi?sstr=3701710",
"absolute_magnitude_h": 20.23,
"estimated_diameter": {
"kilometers": {
}
And that's the way it is built in Visual Studio (using the Special Paste option for JSON)
public class NearEarthObject
{
public Links links { get; set; }
public int element_count { get; set; }
public Near_Earth_Objects near_earth_objects { get; set; }
}
public class Links
{
public string next { get; set; }
public string prev { get; set; }
public string self { get; set; }
}
public class Near_Earth_Objects
{
public _20210703[] _20210703 { get; set; }
}
public class _20210703
{
public Links1 links { get; set; }
public string id { get; set; }
public string neo_reference_id { get; set; }
public string name { get; set; }
public string nasa_jpl_url { get; set; }
public float absolute_magnitude_h { get; set; }
public Estimated_Diameter estimated_diameter { get; set; }
public bool is_potentially_hazardous_asteroid { get; set; }
public Close_Approach_Data[] close_approach_data { get; set; }
public bool is_sentry_object { get; set; }
}
The question is, inside of the element "near_earth_objects", there is an element called "2021-07-03" (the date of the data I requested), the problem is that I am trying to include it into a DataGridView made in .NET C# (Windows Forms, but that doesn't matters here, I think) and the user wants to get the information by date. So, "2021-07-03" is a valid member just for one day, and the user should be able to get data from multiple days.
So, is there a way in C# to get all child objects inside of near_earth_objects without knowing their names since there will be the option to search for asteroids from date X to Y in my application?
Using System.Text.Json
The API response will map to the following classes
public class Neo
{
public Links Links { get; set; }
public int ElementCount { get; set; }
public Dictionary<string, List<NearEarthObject>> NearEarthObjects { get; set; }
}
public class Links
{
public string Next { get; set; }
public string Prev { get; set; }
public string Self { get; set; }
}
public class NearEarthObject
{
public Links Links { get; set; }
public string Id { get; set; }
public string Name { get; set; }
// Other properties
}
The NearEarthObjects is simply a Dictionary, where the key is the formatted date and value is a List containing NearEarthObject
The PropertyNamingPolicy will allow us to support the API's underscore property naming convention.
public class UnderscoreNamingPolicy : JsonNamingPolicy
{
public override string ConvertName(string name)
{
return name.Underscore();
}
}
Example usage
// using using System.Text.Json;
var response = await new HttpClient().GetStringAsync(url);
var neo = JsonSerializer.Deserialize<Neo>(response, new JsonSerializerOptions
{
PropertyNamingPolicy = new UnderscoreNamingPolicy()
});
foreach(var neos in neo.NearEarthObjects)
{
Console.WriteLine(neos.Key);
}
use System.Text.Json, JsonNamingPolicy
demo code
public class DynamicNamePolicy : JsonNamingPolicy
{
public override string ConvertName(string name)
{
var today = DateTime.Today.ToString("yyyy-MM-dd");
if (name.Equals("DateData")) //model property name
return today; //convert to json string property name
return name;
}
}
//data deserialize
string data = ""; //json string
var obj = JsonSerializer.Deserialize<NearEarthObject>(data, new JsonSerializerOptions
{
PropertyNamingPolicy = new DynamicNamePolicy(),
});
I'm trying to create a page rendered in .net core 3.1 which renders pages based on JSON.
How can I deserialzie the JSON at the end of this post?
I've tried to deserialize this however it doesn't work because I loose the data for each Component,
since the Page class has a List<Component> - but I need this to be a list of varying different components.
Page Model :
public class Page
{
public int id { get; set; }
public string pagename { get; set; }
public string metatitle { get; set; }
public string metadescription { get; set; }
public string created_at { get; set; }
public string updated_at { get; set; }
public List<Component> components { get; set; }
}
public class Pages
{
public List<Page> pages { get; set; }
}
Component Model:
public class Component
{
public string component { get; set; }
public int id { get; set; }
}
A Component :
public class Title : Component
{
public string component { get; set; }
public int id { get; set; {
public string titletext { get; set; }
}
This is the JSON:
{
"id":1,
"pagename":"home",
"metatitle":"no title",
"metadescription":"no meta",
"created_at":"2020-05-31T16:35:52.084Z",
"updated_at":"2020-05-31T16:35:52.084Z",
"components":[
{
"component":"components.titletext",
"id":1,
"titletext":"hello"
},
{
"component":"components.section",
"id":2,
"titletext":"hello",
"descriptiontext":"its a beatiful day in lost santos",
"buttonlink":"/go"
},
{
"component":"components.cta",
"id":3,
"sectiontitle":"hello",
"buttonlink":"/go",
"buttontext":"click me"
}
]
}
If you don't want to add all properties to the Component class like that:
public class Component
{
public string component { get; set; }
public int id { get; set; }
public string titletext { get; set; }
public string sectiontitle { get; set; }
public string buttonlink { get; set; }
public string descriptiontext { get; set; }
}
You will need to write custom JsonConverter for example (not very performant implementation but works with your json and you will not need to parse every field by hand):
public class ComponentConverter : JsonConverter<Component>
{
public override Component Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
using (var doc = JsonDocument.ParseValue(ref reader))
{
var type = doc.RootElement.GetProperty(#"component").GetString();
switch(type)
{
case "components.titletext":
return JsonSerializer.Deserialize<Title>(doc.RootElement.GetRawText());
// other types handling
default: return JsonSerializer.Deserialize<Component>(doc.RootElement.GetRawText());
}
}
}
public override void Write(Utf8JsonWriter writer, Component value, JsonSerializerOptions options)
{
throw new NotImplementedException();
}
}
public class Component
{
public string component { get; set; }
public int id { get; set; }
}
public class Title : Component
{
public string titletext { get; set; }
}
And usage example:
var json = #"[
{
""component"":""components.titletext"",
""id"":1,
""titletext"":""hello""
},
{
""component"":""components.section"",
""id"":2,
""titletext"":""hello"",
""descriptiontext"":""its a beatiful day in lost santos"",
""buttonlink"":""/go""
},
{
""component"":""components.cta"",
""id"":3,
""sectiontitle"":""hello"",
""buttonlink"":""/go"",
""buttontext"":""click me""
}
]";
var deserializeOptions = new JsonSerializerOptions();
deserializeOptions.Converters.Add(new ComponentConverter());
JsonSerializer.Deserialize<List<Component>>(json, deserializeOptions).Dump();
Also do not use this converter as parameter for JsonConverterAttribute cause it will end in stackoverflow.
If you want/need completely separate unrelated classes you could use a technique that doesn't use a converter:
var ays = new List<A>();
var bees = new List<B>();
using var doc = JsonDocument.Parse(json);
foreach (var block in doc.RootElement.EnumerateArray())
{
switch (block.GetProperty("component").GetString())
{
case "typeA": ays.Add(Deserialise<A>(block)); break;
case "typeB": bees.Add(Deserialise<B>(block)); break;
// ... case
//default: ...
}
}
var composite = new
{
As = ays,
Bs = bees
};
// This is OK, but if you need to speed it up, please have a look at
// https://stackoverflow.com/questions/58138793/system-text-json-jsonelement-toobject-workaround
static T Deserialise<T>(JsonElement e) => JsonSerializer.Deserialize<T>(e.GetRawText(), options: new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
I have the following problem-
I'm trying to serialize a class which contains a class that has an additional dictionary.
The structure is simplified to the following:
public class GroupVM
{
public GroupVM()
{
this.Clusters = new Dictionary<int, ClusterVM>();
}
public Dictionary<int,ClusterVM> Clusters { get; set; }
}
public class ClusterVM
{
public ClusterVM()
{
this.Attributes = new Dictionary<Guid, AttributeVM>();
}
Dictionary<Guid,AttributeVM> Attributes { get; set; }
public void AddAttribute(Guid guid, string name)
{
AttributeVM attrVM = new AttributeVM();
attrVM.Name = name;
attrVM.Guid = guid;
this.Attributes.Add(guid,attrVM);
}
}
public class AttributeVM
{
public Guid Guid { get; set; }
public string Name { get; set; }
}
I'm trying to use it in API, and return a serialized version of GroupVM. For some reason, I'm getting nothing in the Attributes Dictionary (inside ClusterVM class).
If I change it to List, it works fine.
Code Sample
According to the sample code the Attributes property was not public
Dictionary<Guid,AttributeVM> Attributes { get; set; }
It could not get serialized because the serializer was unaware of its presence. Make the property public and it should get serialized.
public class ClusterVM {
public ClusterVM() {
this.Attributes = new Dictionary<Guid, AttributeVM>();
}
public IDictionary<Guid,AttributeVM> Attributes { get; set; }
public void AddAttribute(Guid guid, string name) {
AttributeVM attrVM = new AttributeVM();
attrVM.Name = name;
attrVM.Guid = guid;
this.Attributes.Add(guid,attrVM);
}
}
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; }
}
I have an API I am receiving data from. That API is out of my control on how it is structured, and I need to serialize and deserialize the JSON output to map the data to my model.
Everything works well where JSON is nicely formatted with named properties.
What can you do where there is no named value and there is just an array of ints and strings? like under locations
here is a sample of the JSON:
{"id":"2160336","activation_date":"2013-08-01","expiration_date":"2013-08-29","title":"Practice Manager","locations":{"103":"Cambridge","107":"London"}}
I have models that are like:
public class ItemResults
{
public int Id { get; set; }
public DateTime Activation_Date { get; set; }
public DateTime Expiration_Date{ get; set; }
public string Title { get; set; }
public Location Locations { get; set; }
}
public class Location
{
public int Id { get; set; }
public string value { get; set; }
}
and I am mapping using the inbuilt ajax serialization:
protected T MapRawApiResponseTo<T>( string response )
{
if ( string.IsNullOrEmpty( response ) )
{
return default( T );
}
var serialize = new JavaScriptSerializer();
return serialize.Deserialize<T>( response );
}
var results = MapRawApiResponseTo<ItemResults>(rawApiResponse);
So the ID and all other properties are picked up and mapped but what every I do I can not seem to map the locations.
Many thanks
public Dictionary<int,string> Locations { get; set; }
job done; you should find that using Json.NET, at least, i.e.
var result = JsonConvert.DeserializeObject<ItemResults>(json);
you get 2 entries in result.Locations; specifically result[103] = "Cambridge"; and result[107] = "London";
If you don't mind, you can workaround with dictionary:
class Program
{
static void Main(string[] args)
{
string json =
"{'id':'2160336','activation_date':'2013-08-01','expiration_date':'2013-08-29','title':'Practice Manager','locations':{'103':'Cambridge','107':'London'}}";
var deserializeObject = JsonConvert.DeserializeObject<ItemResults>(json);
Console.WriteLine("{0}:{1}", deserializeObject.Locations.First().Key, deserializeObject.Locations.First().Value);
Console.ReadKey();
}
}
public class ItemResults
{
public int Id { get; set; }
public DateTime Activation_Date { get; set; }
public DateTime Expiration_Date { get; set; }
public string Title { get; set; }
public Dictionary<int, string> Locations { get; set; }
}
you can also use manual parsing, like here: Json.NET (Newtonsoft.Json) - Two 'properties' with same name?
This will work:
public Dictionary<string, string> Locations { get; set; }
public IEnumerable<Location> LocationObjects { get { return Locations
.Select(x => new Location { Id = int.Parse(x.Key), value = x.Value }); } }
I propose you the following solution :
public class ItemResults
{
public int Id { get; set; }
public DateTime Activation_Date { get; set; }
public DateTime Expiration_Date { get; set; }
public string Title { get; set; }
[JsonProperty("locations")]
public JObject JsonLocations { get; set; }
[JsonIgnore]
public List<Location> Locations { get; set; }
[OnDeserialized]
public void OnDeserializedMethod(StreamingContext context)
{
this.Locations = new List<Location>();
foreach (KeyValuePair<string, JToken> item in this.JsonLocations)
{
this.Locations.Add(new Location() { Id = int.Parse(item.Key), value = item.Value.ToString() });
}
}
}
public class Location
{
public int Id { get; set; }
public string value { get; set; }
}
After you just have to deserialize your JSON with : JsonConvert.DeserializeObject<ItemResults>(json);