Being a VB.Net programmer using VB.Net 2015 community, I come across items in C# that I need to convert to VB, but this time I don't understand what I'm working with. The website service I'm consuming returns and expects JSON / JOBJECTS structures like:
var token = new {
iss = PARTNERID,
product = "twpemp",
sub = "partner",
siteInfo = new {
type = "id",
id = SITEID
},
exp = (Int32)DateTime.UtcNow.Add(new TimeSpan(0, 4, 30)).Subtract(new DateTime(1970, 1, 1)).TotalSeconds
};
An online converter converted this into:
Dim EPochTime = DateTime.UtcNow.Add(New TimeSpan(0, 4, 0)).Subtract(New DateTime(1970, 1, 1)).TotalSeconds
Dim Token = New With {
Key .iss = AccNumber,
Key .product = "twppartner",
Key .sub = "partner",
Key .siteInfo = New With {
Key .type = "id",
Key .id = Site},
Key .exp = EPochTime
}
I need to dynamically create this type of structures because the "key name" and values change depending on what was returned and needs to be sent back. For example, depending on the siteid from above, the returning structure might have stuff like:
"Results": [
{
"RecordNumber": 000001,
"EmployeeCode": "0001",
"FirstName": "John",
"MiddleName": "A",
"LastName": "Dow",
"Designation": "Worker",
"Home1": "Press",
},
{
"RecordNumber": 000002,
"EmployeeCode": "0002",
"FirstName": "Jane",
"MiddleName": "b",
"LastName": "Dow",
"Designation": "Helper",
"Home1": "Office",
}
}
For the next client I submit a query for, and eventually need to update with might have:
"Results": [
{
"RecordNumber": 12345,
"EmployeeCode": "231",
"FirstName": "Erick",
"MiddleName": "G",
"LastName": "Smith",
"Department": "Electrial",
},
{
"RecordNumber": 732456,
"EmployeeCode": "853",
"FirstName": "Fred",
"MiddleName": "W",
"LastName": "Kerber",
"Department": "Electrial",
}
}
The difference between the two is one has "Department" and the other doesn't. This structure changes based on the siteID from the first call.
My main question is how do I create something like this dynamically in VB.NET, and secondarily, exactly what is this type of thing called? I'm calling it a structure for lack of better words.
If you want a little more flexibility with outputting this stuff in JSON, there are two approaches:
1) You can use Dictionary<string,object> instead of dynamic types. With the dictionary approach, you can add (or exclude) properties at run-time. The JSON serializer will output in the same fashion as if you were serializing a dynamic type.
var dict = new Dictionary<string, object>() { { "key1", "value1"} };
dict["key2"] = DateTime.Now();
dict["key3"] = 1234567;
if (someCondition){
dict["key4"] = new Dictionary<string, object>() { { "key5", "value5"}, { "key6", "value6"}};
}
2) You can create a class that has ALL the available properties that the JSON structure might include. For optional properties which are numeric types, make them nullable:
public class Qwijibo
{
public int? RecordNumber {get;set;}
public string EmployeeCode {get;set;}
public string FirstName {get;set;}
public string MiddleName {get;set;}
public string LastName {get;set;}
public string Designation {get;set;}
public string Home1 {get;set;}
public string Department {get;set;
}
The above class may work in both the scenarios you presented. Properties you don't assign a value to will serialize as null in JSON. As long as whatever you're transmitting to doesn't get hung up on null values, you're good to go.
Related
I have a json file and I deserialised it as shown in the code below. Some context, dex is a robot and it has information such as battery and so on as shown in the json file below. I want to read the battery status for the robot that the user selected ( robot).
This is my code, currently im only accessing data.dex but i want to change it to whichever data.robot, where robot is a variable
var data = JsonConvert.DeserializeObject<Root>(json);
var robot = queryDetails2.Amr;
var text =$"";
if (data.dex.battery.status == "good")
{
text = $"{queryDetails2.Amr}'s battery is in good condition. ";
}
This is the json file:
{
"dex":
{
"current_job":
{"job":null, "task": null, "location": null},
"battery":
{"name":"battery", "status": "good", "value": "100"},
},
"dex_1":
{
"current_job":
{"job":null, "task": null, "location": null},
"battery":
{"name":"battery", "status": "good", "value": "100"},
},
"dex_2":
{
"current_job":
{"job":null, "task": null, "location": null},
"battery":
{"name":"battery", "status": "good", "value": "100"},
}
}
I wanted to use the GetMethod or the solution as suggested in this question (https://stackoverflow.com/questions/53076743/how-to-access-variable-of-a-nested-functions-in-python[1]).
However, im getting errors like it does not have a method. Now im confused, was it because i used var? but the deserialised method converts the json to an object though..
Anyway, how should i approach this?
Assuming that you have 3 robots with different names: dex, dex_1 and dex_2, you should reorganize your solution to treat the json data as a list of Robots instead of 3 separate variables for each robot.
To do this, first your json should look like this:
{
"robots":[
{
"name":"dex",
"current_job":{
"job":null,
"task":null,
"location":null
},
"battery":{
"name":"battery",
"status":"good",
"value":"100"
}
},
{
"name":"dex_1",
"current_job":{
"job":null,
"task":null,
"location":null
},
"battery":{
"name":"battery",
"status":"good",
"value":"100"
}
},
{
"name":"dex_2",
"current_job":{
"job":null,
"task":null,
"location":null
},
"battery":{
"name":"battery",
"status":"good",
"value":"100"
}
}]
}
Next, update your serialization classes. Add a field called name in the Robot class or whatever class type you currently have for data.dex. In Root, remove the "dex" fields and add a List<Robot>.
public class Root
{
public List<Robot> robots { get; set; }
}
public class Robot
{
public string name { get; set; }
public Job current_job { get; set;}
public Battery battery{ get; set; }
}
Now you can write whatever logic to get the right robot data. Here is an example using System.Linq:
var robotName = "dex_2";
var robotInfo = data.robots.First(x => x.name.Equals(robotName));
var text = $"{robotName}'s battery is in {robotInfo.battery.status} condition.";
Right now I have the following code to query my CosmosDB:
var streamIterator = containerLogs.GetItemQueryStreamIterator("SELECT * FROM mycontainer");
while (streamIterator.HasMoreResults)
{
var results = await streamIterator.ReadNextAsync();
var stream = results.Content;
using var reader = new StreamReader(stream);
string data = await reader.ReadToEndAsync();
// typeof what..?
//var dbDocuments = JsonConvert.DeserializeObject<???>(data);
}
The variable data will contain the following JSON:
{
"_rid": "wDhMAJ9xYHE=",
"Documents": [{
"id": "c05c4eee-32d4-458a-8ae8-d22dd0f93839",
"CustomProperty1": "Value 1",
"CustomProperty2": "Value 2",
"_rid": "wDhMAJ9xYHECAAAAAAAAAA==",
"_self": "dbs\/wDhMAA==\/colls\/wDhMAJ9xYHE=\/docs\/wDhMAJ9xYHECAAAAAAAAAA==\/",
"_etag": "\"00000000-0000-0000-7167-28c107aa01d6\"",
"_attachments": "attachments\/",
"_ts": 1597319093
}],
"_count": 1
}
The Documents part is my actual "domain" model. How can I easily map this back to a list of my domain model class? I used the same class to write to CosmosDB.
The model looks like this
public class MyModel
{
[JsonProperty(PropertyName = "id")]
public Guid Id {get;set;}
public string CustomProperty1 {get;set;}
public string CustomProperty1 {get;set;}
}
So how can I query my CosmosDB so that it returns a list of this class?
Here are some samples that I found helpful. The simpler case is to used the typed GetItemQueryIterator<MyModel>, but there is also a stream deserialization example.
I am looking at one WebAPI application sample that has this coded:
json.SerializerSettings.PreserveReferencesHandling
= Newtonsoft.Json.PreserveReferencesHandling.Objects;
and another with this coded:
json.SerializerSettings.ReferenceLoopHandling
= Newtonsoft.Json.ReferenceLoopHandling.Ignore;
Neither explain why each is chosen. I'm very new to WebAPI, so can someone help by explaining to me in simple terms what the differences are and why I might need to use one over the other.
These settings can best be explained by example. Let's say that we want to represent a hierarchy of employees in a company. So we make a simple class like this:
class Employee
{
public string Name { get; set; }
public List<Employee> Subordinates { get; set; }
}
This is a small company with only three employees so far: Angela, Bob and Charles. Angela is the boss, while Bob and Charles are her subordinates. Let's set up the data to describe this relationship:
Employee angela = new Employee { Name = "Angela Anderson" };
Employee bob = new Employee { Name = "Bob Brown" };
Employee charles = new Employee { Name = "Charles Cooper" };
angela.Subordinates = new List<Employee> { bob, charles };
List<Employee> employees = new List<Employee> { angela, bob, charles };
If we serialize the list of employees to JSON...
string json = JsonConvert.SerializeObject(employees, Formatting.Indented);
Console.WriteLine(json);
...we get this output:
[
{
"Name": "Angela Anderson",
"Subordinates": [
{
"Name": "Bob Brown",
"Subordinates": null
},
{
"Name": "Charles Cooper",
"Subordinates": null
}
]
},
{
"Name": "Bob Brown",
"Subordinates": null
},
{
"Name": "Charles Cooper",
"Subordinates": null
}
]
So far so good. You'll notice, however, that the information for Bob and Charles is repeated in the JSON because the objects representing them are referenced both by the main list of employees and Angela's list of subordinates. Maybe that's OK for now.
Now suppose we'd also like to have a way to keep track of each Employee's supervisor in addition to his or her subordinates. So we change our Employee model to add a Supervisor property...
class Employee
{
public string Name { get; set; }
public Employee Supervisor { get; set; }
public List<Employee> Subordinates { get; set; }
}
...and add a couple more lines to our setup code to indicate that Charles and Bob report to Angela:
Employee angela = new Employee { Name = "Angela Anderson" };
Employee bob = new Employee { Name = "Bob Brown" };
Employee charles = new Employee { Name = "Charles Cooper" };
angela.Subordinates = new List<Employee> { bob, charles };
bob.Supervisor = angela; // added this line
charles.Supervisor = angela; // added this line
List<Employee> employees = new List<Employee> { angela, bob, charles };
But now we have a bit of a problem. Because the object graph has reference loops in it (e.g. angela references bob while bob references angela), we will get a JsonSerializationException when we try to serialize the employees list. One way we can get around this issue is by setting ReferenceLoopHandling to Ignore like this:
JsonSerializerSettings settings = new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
Formatting = Formatting.Indented
};
string json = JsonConvert.SerializeObject(employees, settings);
With this setting in place, we get the following JSON:
[
{
"Name": "Angela Anderson",
"Supervisor": null,
"Subordinates": [
{
"Name": "Bob Brown",
"Subordinates": null
},
{
"Name": "Charles Cooper",
"Subordinates": null
}
]
},
{
"Name": "Bob Brown",
"Supervisor": {
"Name": "Angela Anderson",
"Supervisor": null,
"Subordinates": [
{
"Name": "Charles Cooper",
"Subordinates": null
}
]
},
"Subordinates": null
},
{
"Name": "Charles Cooper",
"Supervisor": {
"Name": "Angela Anderson",
"Supervisor": null,
"Subordinates": [
{
"Name": "Bob Brown",
"Subordinates": null
}
]
},
"Subordinates": null
}
]
If you examine the JSON, it should be clear what this setting does: any time the serializer encounters a reference back to an object it is already in the process of serializing, it simply skips that member. (This prevents the serializer from getting into an infinite loop.) You can see that in Angela's list of subordinates in the top part of the JSON, neither Bob nor Charles show a supervisor. In the bottom part of the JSON, Bob and Charles both show Angela as their supervisor, but notice her subordinates list at that point does not include both Bob and Charles.
While it is possible to work with this JSON and maybe even reconstruct the original object hierarchy from it with some work, it is clearly not optimal. We can eliminate the repeated information in the JSON while still preserving the object references by using the PreserveReferencesHandling setting instead:
JsonSerializerSettings settings = new JsonSerializerSettings
{
PreserveReferencesHandling = PreserveReferencesHandling.Objects,
Formatting = Formatting.Indented
};
string json = JsonConvert.SerializeObject(employees, settings);
Now we get the following JSON:
[
{
"$id": "1",
"Name": "Angela Anderson",
"Supervisor": null,
"Subordinates": [
{
"$id": "2",
"Name": "Bob Brown",
"Supervisor": {
"$ref": "1"
},
"Subordinates": null
},
{
"$id": "3",
"Name": "Charles Cooper",
"Supervisor": {
"$ref": "1"
},
"Subordinates": null
}
]
},
{
"$ref": "2"
},
{
"$ref": "3"
}
]
Notice that now each object has been assigned a sequential $id value in the JSON. The first time that an object appears, it is serialized in full, while subsequent references are replaced with a special $ref property that refers back to the original object with the corresponding $id. With this setting in place, the JSON is much more concise and can be deserialized back into the original object hierarchy with no additional work required, assuming you are using a library that understands the $id and $ref notation produced by Json.Net / Web API.
So why would you choose one setting or the other? It depends on your needs of course. If the JSON will be consumed by a client that does not understand the $id/$ref format, and it can tolerate having incomplete data in places, you would choose to use ReferenceLoopHandling.Ignore. If you're looking for more compact JSON and you will be using Json.Net or Web API (or another compatible library) to deserialize the data, then you would choose to use PreserveReferencesHandling.Objects. If your data is a directed acyclic graph with no duplicate references then you don't need either setting.
The explaination is perfect. For me the below one worked, data is your object.
However, if the above-mentioned method did not work, you can try this one:
string json = JsonConvert.SerializeObject(data, Formatting.Indented,new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
});
I am getting following json format after hitting to an API:
{
"7407": {
"survey_id": "406",
"device_id": "1",
"response_time": "2013-10-10 16:14:01",
"timezone": "0",
"language_id": "en",
"response_id": "7407",
"device_alias": "QR Code App",
"site_name": "QR Code App",
"country_name": "United States",
"state_name": "New York",
"city_name": "Suffern",
"zip": "",
"voucher_name": null,
"voucher_mode": null,
"surveyee_name": null,
"surveyee_email": null,
"surveyee_phone": null,
"ques": {
"": []
}
},
"7408": {
"survey_id": "406",
"device_id": "1",
"response_time": "2013-10-10 16:36:56",
"timezone": "0",
"language_id": "en",
"response_id": "7408",
"device_alias": "QR Code App",
"site_name": "QR Code App",
"country_name": "India",
"state_name": "Gujarat",
"city_name": "Ahmedabad",
"zip": "",
"voucher_name": null,
"voucher_mode": null,
"surveyee_name": null,
"surveyee_email": null,
"surveyee_phone": null,
"ques": {
"": []
}
} }
I am using JSON.Net to read the above given json data.
To map this data into .Net code, I will need classes in .net, having same properties' name as in json string.
BUT there are some attributes in json which can be dynamic ("7407", "7408" etc in my case) i.e. this value can be changed based on what are we passing into parameters.
My question is, how can we map json attributes (which are dynamic in nature and can have any value depending upon the parameters provided to the apis) to our .net class ?
You could map it to a Dictionary. Where your dynamic property is the Key of a DictionaryIem and the Objet is the Value of your DictionaryItem.
For Exmaple:
public class MyClass
{
public void readJson)
{
var json = "{\"7407\": {\"survey_id\": \"406\",\"device_id\": \"1\",},\"7408\": {\"survey_id\": \"406\",\"device_id\": \"1\",}}";
Dictionary<int, MyObject> dict = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<int, MyObject>>(json);
var count = dict.Keys.Count;
}
}
public class MyObject
{
public string survey_id { get; set; }
public string device_id { get; set; }
}
For this exmaple i simplified your json. so that it looks like this:
{
"7407": {
"survey_id": "406",
"device_id": "1"
},
"7408": {
"survey_id": "406",
"device_id": "1"
}
}
Js object is a dictionary, so you can map to Dictionary with key = some attribute, and value - .Net code what you want
Dictionary<object,'your data class'>
The best way I could find handling this kind of JSON data is by using JObject class of the JSON.Net library.
For eg:
Newtonsoft.Json.Linq.JObject jSonObject = JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JObject>(somejsonstring);
and then you can loop through or apply some other logic to read jSonObject
I know this is not hard, but I've been staring at the JSON.Net documentation for a half hour and don't see how it works. I've got it setup, but my initial attempts are failing and the documenation that I have looked at so far isn't making it obvious (to me, at least) how to deserialize the array form response.data and then get at the individual fields of each record.
Also, I don't need to use JSON.Net - it just seemed like a good choice. Any solution will do just fine.
{
"request":{
"Format":"json",
"Target":"Affiliate",
"Method":"findAll",
"Service":"HasOffers",
"Version":"2",
"NetworkId":"directagents",
"NetworkToken":"......"
},
"response":{
"status":1,
"data":{
"2056":{
"Affiliate":{
"id":"2056",
"company":
"123 Greetings 123 Greetings (CD186)",
"address1":"1 Change Address",
"address2":"",
"city":"City",
"region":"NY",
"country":"US",
"other":null,
"zipcode":"11111",
"phone":"-",
"fax":null,
"website":null,
"signup_ip":null,
"date_added":"2012-02-24 18:00:24",
"modified":-62169966000,
"ref_id":"CD186",
"status":"pending",
"wants_alerts":"1",
"account_manager_id":"20",
"payment_method":"check",
"payment_terms":"net 30",
"w9_filed":"0",
"referral_id":null,
"affiliate_tier_id":null,
"fraud_activity_score":null,
"fraud_activity_alert_threshold":null,
"fraud_activity_block_threshold":null,
"fraud_profile_alert_threshold":null,
"fraud_profile_block_threshold":null,
"scrub_offer_pixels":null,
"shared":"0"
}
},
"1606":{
.......this is enough to see how its structured....
You could model that “array” as Dictionary<int, AffiliateHolder>. The classes for that JSON could look like this:
class Top
{
public Request Request { get; set; }
public Response Response { get; set; }
}
class Request
{
public string Format { get;set; }
// etc.
}
class Response
{
public int Status { get; set; }
public Dictionary<int, AffiliateHolder> Data { get; set; }
}
class AffiliateHolder
{
public Affiliate Affiliate { get; set; }
}
class Affiliate
{
public int Id { get; set; }
// etc.
}
var o = JsonConvert.DeserializeObject<Top>(myJSONString);
The fastest, easiest way is to use Json.NET and LINQ to Json. Given your example above, the following code:
var parsedJson = JObject.Parse(rawJson);
foreach (var item in parsedJson["response"]["data"])
{
Console.WriteLine(item.ToString());
}
would write out the following to the console:
"2056": {
"Affiliate": {
"id": "2056",
"company": "123 Greetings 123 Greetings (CD186)",
"address1": "1 Change Address",
"address2": "",
"city": "City",
"region": "NY",
"country": "US",
"other": null,
"zipcode": "11111",
"phone": "-",
"fax": null,
"website": null,
"signup_ip": null,
"date_added": "2012-02-24 18:00:24",
"modified": -62169966000,
"ref_id": "CD186",
"status": "pending",
"wants_alerts": "1",
"account_manager_id": "20",
"payment_method": "check",
"payment_terms": "net 30",
"w9_filed": "0",
"referral_id": null,
"affiliate_tier_id": null,
"fraud_activity_score": null,
"fraud_activity_alert_threshold": null,
"fraud_activity_block_threshold": null,
"fraud_profile_alert_threshold": null,
"fraud_profile_block_threshold": null,
"scrub_offer_pixels": null,
"shared": "0"
}
}
It is not necessary to create concrete classes for explicit deserialization. Obviously that is a perfectly valid approach, however, if that's your style preference.
See http://james.newtonking.com/projects/json/help/LINQtoJSON.html for more examples.
I think you can try creating a simple example, not a huge json like that one.
Take a look at http://servicestack.net/ it is an alternative to Json.NET, it is faster and the learning curve is small. You can find a lot of examples on the website.
Is this in javascript? You should be able to just do this:
JSON.parse(response.data)