JSON Parse Bank Holiday Calendar - c#

I have a ASP MVC project that is accessing an API to get bank holiday dates: https://www.gov.uk/bank-holidays.json
When I parse the JSON however I am getting problems when I try to get down to the level of the 'events'. Currently I have:
var json = new WebClient().DownloadString("https://www.gov.uk/bank-holidays.json");
JavaScriptSerializer serializer = new JavaScriptSerializer();
var test = serializer.Deserialize<Dictionary<string, Dictionary<string, object>>>(json);
I can't seem to be able to cast the final object in this deserializer to anything meaningful. I have tried a variety of objects, lists, arrays etc but nothing seem to work. I only ever seem to be able to cast it to object.
Ideally I'd like the JSON to be parsed to a meaningful object such as:
public class BankHoliday
{
public DateTime Date { get; set; }
public string Title { get; set; }
public Country CountryCode { get; set; }
public string Notes { get; set; }
public bool Bunting { get; set; }
}
public enum Country
{
EnglandWales,
Scotland,
NorthernIreland
}
I thought this would be fairly simple but I have tried everything. I'm sure it's something simple that I am missing.
Thanks

Don't use JavaScriptSerializer better choice is JSON.NET
On site json2csharp.com you can generate classes from JSON:
public class Event
{
public string title { get; set; }
public string date { get; set; }
public string notes { get; set; }
public bool bunting { get; set; }
}
public class EnglandAndWales
{
public string division { get; set; }
public List<Event> events { get; set; }
}
public class Scotland
{
public string division { get; set; }
public List<Event> events { get; set; }
}
public class NorthernIreland
{
public string division { get; set; }
public List<Event> events { get; set; }
}
public class RootObject
{
[JsonProperty(PropertyName = "england-and-wales")]
public EnglandAndWales EnglandAndWales { get; set; }
public Scotland scotland { get; set; }
[JsonProperty(PropertyName = "northern-ireland")]
public NorthernIreland NorthernIreland { get; set; }
}
And then deserialise it with this way:
RootObject rootObject = JsonConvert.DeserializeObject<RootObject>(output);
EDIT
Added properties in RootObject to handele bad names.
Tested on simplified JSON:
{
"england-and-wales": {
"division": "england-and-wales",
"events": [{
"title": "New Year’s Day",
"date": "2012-01-02",
"notes": "Substitute day",
"bunting": true
},
{
"title": "Good Friday",
"date": "2012-04-06",
"notes": "",
"bunting": false
},
{
"title": "Boxing Day",
"date": "2017-12-26",
"notes": "",
"bunting": true
}]
},
"scotland": {
"division": "scotland",
"events": [{
"title": "2nd January",
"date": "2012-01-02",
"notes": "",
"bunting": true
},
{
"title": "New Year’s Day",
"date": "2012-01-03",
"notes": "Substitute day",
"bunting": true
},
{
"title": "Boxing Day",
"date": "2017-12-26",
"notes": "",
"bunting": true
}]
},
"northern-ireland": {
"division": "northern-ireland",
"events": [{
"title": "New Year’s Day",
"date": "2012-01-02",
"notes": "Substitute day",
"bunting": true
},
{
"title": "St Patrick’s Day",
"date": "2012-03-19",
"notes": "Substitute day",
"bunting": true
},
{
"title": "Boxing Day",
"date": "2017-12-26",
"notes": "",
"bunting": true
}]
}
}

I would greatly encourage you to use json.net lirary
I think you key problème here is that you need to use your type (BankHoliday) in the type definition:
Dictionary<string, <Dictionary<string, BankHoliday>>

Why not just use dynamic?
public IHttpActionResult BankHolidays()
{
var rawJson = string.Empty;
using (var webClient = new WebClient())
{
webClient.Encoding = Encoding.UTF8; // Expected Content-Type response is "application/json; charset=utf-8"
rawJson = webClient.DownloadString("https://www.gov.uk/bank-holidays.json");
}
dynamic json = JsonConvert.DeserializeObject<dynamic>(rawJson);
return Ok(json);
}

Related

Generating HMAC signature

I am trying to generate the HMAC signature. This is for a validation with credit card company. Below is my code to generate the HMAC signature:
public string APISecurityKey(Identity postParameters)
{
String secretAccessKey = "secretkey";
string data = "message";
byte[] secretKey = Encoding.UTF8.GetBytes(secretAccessKey);
HMACSHA256 hmac = new HMACSHA256(secretKey);
hmac.Initialize();
byte[] bytes = Encoding.UTF8.GetBytes(data);
byte[] rawHmac = hmac.ComputeHash(bytes);
return Convert.ToBase64String(rawHmac);
}
They are asking me to substitute the message field with the JSON request (JSON supplied should have all carriage return newline sequences replaced with a space character). My object looks like so:
public class Identity
{
public List<Header> header { get; set; }
public string firstName { get; set; }
public string LastName { get; set; }
public string middleName { get; set; }
public string address { get; set; }
public string mothersName { get; set; }
public string DriversLic { get; set; }
public DateTime insertTime { get; set; }
public string Status { get; set; }
public string city { get; set; }
public string state { get; set; }
public string zip { get; set; }
public DateTime UpdatedOn { get; set; }
}
}
public class Header
{
public string tenantId { get; set; }
public string requestType { get; set; }
public string clientReferenceId { get; set; }
public string expRequestId { get; set; }
public string txnId { get; set; }
public string messageTime { get; set; }
public string options { get; set; }
}
The example given to me for the message is like this:
{"tenantId": "TENANT1","request Type": "Simulator","clientRefere
nceId": "Hunter + ProveID","expRequestId": "333","messageTim
e": "2016-08-04T22:13:07Z","options": {"workflow": "wf1","model
Type":"mt1","responseType":1,"Responses": {…}}}
I am not sure how to include tenantId, tenantId, expRequestId, options as part of my JSON message. I am very new to JSON. I have this partial code:
public static async Task createJSON( Identity postParameters)
{
var tmpRequest = new HttpRequestMessage();
tmpRequest.Content = new StringContent(JsonConvert.SerializeObject(postParameters));
tmpRequest.Content.Headers.Add("tenantId", "V123456");
tmpRequest.Content.Headers.Add("requestType", "PreciseIdOnly");
}
postParameters is my Identity object with values. How can I create that JSON that includes tenantId, tenantId, expRequestId and the object so that I can put that JSON value in the message of APISecurityKey method. Below is the test JSON file that I need to create:
{
"header": {
"tenantId": "V123456",
"requestType": "Precise",
"clientReferenceId": "11111111",
"RequestId": "",
"txnId": "",
"messageTime": "2020-05-28T00:00:02Z",
"options": {}
},
"payload": {
"control": [
{
"option": "SUBSCRIBER_PREAMBLE",
"value": "wer"
},
{
"option": "SUBSCRIBER_OPERATOR_INITIAL",
"value": "WS"
},
{
"option": "SUBSCRIBER_SUB_CODE",
"value": "1111111"
},
{
"option": "PID_USERNAME",
"value": "demo"
},
{
"option": "PID_PASSWORD",
"value": "password"
},
{
"option": "PRODUCT_OPTION",
"value": "11"
}
],
"contacts": [{
"id": "APPLICANT_CONTACT_ID_1",
"person": {
"typeOfPerson": "",
"personIdentifier": "",
"personDetails": {
"dateOfBirth": "1990-12-11",
"yearOfBirth": "",
"age": "",
"gender": "",
"noOfDependents": "",
"occupancyStatus": "",
"mothersMaidenName": "",
"spouseName": ""
},
"names": [{
"id": "",
"firstName": "Test1",
"middleNames": "D",
"surName": "Test2",
"nameSuffix": ""
}]
},
"addresses": [{
"id": "Main_Contact_Address_0",
"addressType": "CURRENT",
"poBoxNumber": "",
"street": "2312 Test Drve",
"street2": "",
"postTown": "test",
"postal": "49548",
"stateProvinceCode": "CA"
}],
"identityDocuments": [{
"documentNumber": "123456789",
"hashedDocumentNumber": "",
"documentType": "SSN"
}]
}]
}
}
I want to generate the same JSOn as the sample above in C# using the objects.
any help will be highly appreciated.
If you using Visual studio, you can create the JSON by going to Edit menu and paster JSON as class. This will create all the classes for you and then you can assign values to the classes by instantiating them

Pick out specific, optional key from metavalues object in JSON and store into my class

I'm struggling to make this conversion happen, and not sure it's entirely feasible. My JSON from a third party could look like this:
{
"equipments": [
{
"serialNumber": "11-17-053",
"equipmentType_id": "589dda4952172110008870c7",
"created": 1508856453875,
"fieldOffice_id": "594af5425fbfca00111a0c20",
"clients_id": [],
"notes": "",
"isInService": true,
"metavalues": {
"0t78nzhp9w265avlvt": {
"item_ids": [
33121
]
},
"7ogz4kehqh8h3cwip8": {
"item_ids": [
33128
]
}
},
"schedules": [],
"id": "59ef52854d40a9009c787596"
},
{
"serialNumber": "11-17-054",
"equipmentType_id": "589dda4952172110008870c7",
"created": 1508856453875,
"fieldOffice_id": "594af5425fbfca00111a0c20",
"clients_id": [],
"notes": "",
"isInService": true,
"metavalues": {
"0t78nzhp9w265avlvt": {
"item_ids": [
33121
]
},
"7ogz4kehqh8h3cwip8": {
"item_ids": [
33128
]
}
},
"schedules": [],
"id": "59ef52854d40a9009c787597"
},
{
"serialNumber": "8-17-022",
"equipmentType_id": "589dda4952172110008870c7",
"created": 1505326964589,
"fieldOffice_id": "594af5425fbfca00111a0c20",
"clients_id": [],
"notes": "",
"isInService": true,
"metavalues": {
"0t78nzhp9w265avlvt": {
"item_ids": [
33121
]
},
"7ogz4kehqh8h3cwip8": {
"item_ids": [
33128
]
}
},
"schedules": [],
"id": "59b9777480e426009d01d48d"
},
{
"serialNumber": "22A-17-001",
"equipmentType_id": "589dda4952172110008870c7",
"created": 1504908025733,
"fieldOffice_id": "58b74b080c206710004ff726",
"clients_id": [
"59bbfdf5725cd00012fb15d8"
],
"notes": "",
"isInService": true,
"metavalues": {
"0t78nzhp9w265avlvt": {
"item_ids": [
33122
]
},
"7ogz4kehqh8h3cwip8": {
"item_ids": [
33128
]
},
"g99idmcqyuo2na9e6l": "YARD",
"709pm94prt2tpjt90y": 5,
"bgen1h4i5b6f8xa1kh": "9/8/2017 7:18:24 PM",
"yvtvsl8dedudqjtdud": "0.00000, 0.00000",
"aj3h2b5fdbic9s72m3": "Parex",
"8wt1re82xidjiv8rzi": "YARD"
},
"schedules": [],
"id": "59b312f93256d5009c4a73fb"
},....
This is obviously not a complete example, but should help get my question across.
Is there a way to create a C# class that pulls in certain fields only if they exist from the "metavalues" array?
My current class is as follows which works to get the data, but not exactly how I want.
public class Equipment
{
[JsonProperty("serialNumber")]
public string SerialNumber { get; set; }
public string equipmentType_id { get; set; }
public bool isInService { get; set; }
public List<string> clients_Id { get; set; }
public string fieldOffice_id { get; set; }
[JsonProperty("id")]
public string EquipmentId { get; set; }
[JsonProperty("metavalues")]
public Dictionary<string, object> metavalues { get; set; }
}
What I'm after, is taking the key of "g99idmcqyuo2na9e6l" which is optional in the metavalues, and store it in a property called "LeaseName".
I tried the following to no avail.
public class Equipment
{
[JsonProperty("serialNumber")]
public string SerialNumber { get; set; }
public string equipmentType_id { get; set; }
public bool isInService { get; set; }
public List<string> clients_Id { get; set; }
public string fieldOffice_id { get; set; }
[JsonProperty("id")]
public string EquipmentId { get; set; }
[JsonProperty("g99idmcqyuo2na9e6l")]
public string LeaseName { get; set; }
}
If I try to make a class for the metavalues section, I get an exception indicating that JSON.NET can't convert it to my object, hence why I used the Dictionary<string, object> option.
EDIT # 1: The accepted answer works for me, but for those who stumble upon this and truly need a property name from a nested array you could try the following.
[OnDeserialized]
private void OnDeserialized(StreamingContext context)
{
if (metavalues != null)
{
if (metavalues.ContainsKey("g99idmcqyuo2na9e6l"))
{
string _LeaseName = (string)metavalues["g99idmcqyuo2na9e6l"];
LeaseName = _LeaseName;
}
}
}
I think my edit approach is a bit overkill but just throwing this out there.
Yes, this is possible, but since the lease value is still one level down in the JSON you need an intermediate class to hold it (to replace the dictionary).
public class Equipment
{
...
[JsonProperty("metavalues")]
public MetaValues MetaValues { get; set; }
}
public class MetaValues
{
[JsonProperty("g99idmcqyuo2na9e6l")]
public string LeaseName { get; set; }
}
Fiddle: https://dotnetfiddle.net/Ddqzc7

JSON Desrialize Dictionary

Im trying to deserialize this json, originally the Airlines property is a IList but this doesn't work because the values are changing, so i used Dictionary i can get the key just fine but the values are empty.
This is the Sample JSON i'm trying to deserialize
"airlines": {
"MH": {
"lowcost": true,
"name": "Jetstar Asia",
"alliance_name": null,
"id": 300,
"rates": "18",
"average_rate": "3.12"
},
"PR": {
"lowcost": true,
"name": "Tigerair",
"alliance_name": null,
"id": 800,
"rates": "26",
"average_rate": "3.41"
},
"CZ": {
"lowcost": false,
"name": "Singapore Airlines",
"alliance_name": "Star Alliance",
"id": 449,
"rates": "620",
"average_rate": "4.18"
},
"SQ": {
"lowcost": true,
"name": "AirAsia Zest",
"alliance_name": null,
"id": 839,
"rates": "104",
"average_rate": "2.56"
},
"GA": {
"lowcost": true,
"name": "CEBU Pacific Air",
"alliance_name": null,
"id": 169,
"rates": "72",
"average_rate": "3.44"
},
This is the properties
[JsonProperty("airlines")]
public Dictionary<string, Airlines> Airlines { get; set; }
public class Airlines
{
[JsonProperty("AirlineDetails")]
public ICollection<AirlineDetails> AirlineDetails { get; set; }
}
public class AirlineDetails
{
[JsonProperty("average_rate")]
public string AverageRate { get; set; }
[JsonProperty("alliance_name")]
public string AllianceName { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("lowcost")]
public bool Lowcost { get; set; }
[JsonProperty("id")]
public int Id { get; set; }
[JsonProperty("rates")]
public string Rates { get; set; }
}
Picture below shows there is a count which is 5 exactly as the JSON object count above, but the values are empty, i also want to get the values which is the name of airline.
Empty Value:
Airlines class is not necessary. Declare your property as Dictionary<string, AirlineDetails>:
public Dictionary<string, AirlineDetails> Airlines { get; set; }

Deserialize nested JSON array using RestSharp

Having the following json array:
[{
"Name": "Component1",
"Count": 2,
"Bulletins": [{
"ReferenceNumber": "00000A57",
"Title": "Test test test",
"PublicationDate": "2014-07-02",
"List": ["00000A57"]
},
{
"ReferenceNumber": "10V240000",
"Title": "Bla bla bla",
"PublicationDate": "2010-06-04",
"List": ["10V240000"]
}]
},
{
"Name": "Component2",
"Count": 2,
"Bulletins": [{
"ReferenceNumber": "00-00-0A-57",
"Title": "INFORMATION REGARDING BLA BLA",
"PublicationDate": "2015-05-22",
"List": ["15-00-89-004",
"15-00-89-004A"]
},
{
"ReferenceNumber": "01-02-0B-57",
"Title": "UNSCHEDULED SUPPLEMENTAL SERVICES",
"PublicationDate": "2012-09-28",
"List": ["04-06-01-029",
"04-26-51-029",
"04-26-51-029",
"04-26-51-029",
"04-26-51-029",
"04-26-51-029",
"04-26-51-029"]
}]
}]
I'm using the following code to retrieve the Name and Count values:
public class BulletinsItemsName
{
public string Name { get; set; }
public string Count { get; set; }
public List<BulletinsContainer> blt { get; set; }
}
public class BulletinsContainer
{
public Bulletins Bulletins;
}
public class Bulletins
{
public string ReferenceNumber { get; set; }
public string Title { get; set; }
public string PublicationDate { get; set; }
public string SupersededList { get; set; }
}
To run the request i have:
var req = request.Execute<List<BulletinsItemsName>>(parameters);
And to list values:
foreach(var xx in req.Data)
{
Console.WriteLine(xx.Name);
foreach(var yz in xx.blt) // Object reference not set to an instance of an object
{
Console.WriteLine(yz.Bulletins.Title);
}
}
How can I get values for: ReferenceNumber, Title, PublicationDate and List? All values are correctly returned for Name and Count but when I want to get Bulletins values the following error is thrown: Object reference not set to an instance of an object.
Try using a list of Bulletins instead of BulletinsContainer - It's early morning for me, but I can't see why you need a BulletinsContainer
public List<Bulletins> blt { get; set; }
I would also recommend, if possible, that you name your classes in their singular form.

Can I deserialize a JSON object by object in C#?

I have a big json file. It consist of information of different articles posted on internet. I'm wandering if it's possible to deserialize it object by object. For example, to make a loop and with every iteration a single object from json to be deserialized, then the next one, and so on.
Here are just only two of json file's objects (there are some thousands out there)
[
{
"source": "unimedia",
"title": "some title",
"original_time": "ora: 20:03, 06 dec 2006",
"datetime": "2006-12-06T20:03:00+00:00",
"views": 398,
"comments": 1,
"content": " some content",
"id": "13",
"url": "http://unimedia.info/stiri/-13.html"
},
{
"source": "unimedia",
"title": "some another title",
"original_time": "ora: 20:13, 06 dec 2006",
"datetime": "2006-12-06T20:13:00+00:00",
"views": 173,
"comments": 1,
"content": "some another content",
"id": "19",
"url": "http://unimedia.info/stiri/-19.html"
},
...
]
Here is my class:
class jsonData
{
public string source { get; set; }
public string title { get; set; }
public string original_time { get; set; }
public string datetime { get; set; }
public int views { get; set; }
public int comments { get; set; }
public string content { get; set; }
public int id { get; set; }
public string url { get; set; }
}
Can anybody help me with that ?
You just need to use use Newtonsoft.Json
Newtonsoft Json
string json = File.ReadAllText(PathFile);
jsonData obj = JsonConvert.DeserializeObject<jsonData>(json);

Categories

Resources