how does C# class look like to match this JSON - c#

I have this JSON string that should be posted from JavaScript to the API:
"model": "kpi.availability",
"typeId": "kpi.availability",
"name": "Availability",
"description": "",
"version": "1.0.0",
"properties": {
"X": {
"dataType": "string",
"value": ""
},
"Y": {
"dataType": "number",
"value": 0,
"isMandatory": true
},
"Z": {
"dataType": "number",
"value": 0,
"isMandatory": true
}
}
here we have 3 properties, just for instance, but it can be more than 3 with different names.
And have this C# model which doesn't work
public class KPIType{
public string model { get; set; }
public string typeId { get; set; }
public string name { get; set; }
public string description { get; set; }
public int version { get; set; }
public IDictionary<string, PropertyItem>[] properties { get; set; }
//public List<IDictionary<string, PropertyItem>> properties { get; set; } //Didn't work
}
public class PropertyItem {
public string dataType { get; set; }
public string value { get; set; }
public bool isMandatory { get; set; }
}
But when trying to send it to the backend, it fails at the client side and I'm getting this error:
"The JSON value could not be converted to System.Collections.Generic.IDictionary`2[System.String,ABB.Advanced.Services.Management.Controllers.PropertyItem][]. Path: $.kpiType.properties | LineNumber: 0 | BytePositionInLine: 294."

This JSON is incorrect in array section. It should be like this:
{
"model": "kpi.availability",
"typeId": "kpi.availability",
"name": "Availability",
"description": "",
"version": "1.0.0",
"properties": [
{
"dataType": "string",
"value": "",
"isMandatory": true
},
{
"dataType": "number",
"value": 0,
"isMandatory": true
},
{
"dataType": "number",
"value": 0,
"isMandatory": true
}
]
}
If you want to pass objects with names into property array then you need to add "name" property to the object and then find it in your service by the name.
Exempli gratia:
"properties": [
{
"name": "A",
"dataType": "string",
"value": "",
"isMandatory": true
},
{
"name": "B",
"dataType": "number",
"value": 0,
"isMandatory": true
},
{
"name": "C",
"dataType": "number",
"value": 0,
"isMandatory": true
}
]

Two things are obvious mismatch:
Properties in C# is array, but in JSON file it is an object. Not sure what's the best to fix it, maybe best change the JSON file itself, if possible
isMandatory is bool, that is, required. However, in X it is missing. If it is optional - change it to bool?

Just remove the "[]" in front of the field "properties":
I mean use this:
public IDictionary<string, PropertyItem>[] properties { get; set; }
Replace it with:
public IDictionary<string, PropertyItem> Properties { get; set; }
I highly recommend you use a better naming convention on your class fields according to the Microsoft official
docs
NOTE: If your JSON deserialization is case sensitive you can use the [JsonProperty] attribute on your props like this:
[JsonProperty("properties")
public IDictionary<string, PropertyItem> Properties { get; set; }
public class PropertyItem
{
[JsonProperty("dataType")]
public string DataType { get; set; }
[JsonProperty("value")]
public string Value { get; set; }
[JsonProperty("isMandatory")]
public bool IsMandatory { get; set; }
}

Related

Add item to JSON array section in C#

{
"name": "Not Okay Bears Solana #1",
"image": "ipfs://QmV7QPwmfc6iFXw2anb9oPZbkFR75zrtw6exd8LherHgvU/1.png",
"attributes": [
{
"trait_type": "Background",
"value": "Amethyst"
},
{
"trait_type": "Fur",
"value": "Warm Ivory"
},
{
"trait_type": "Mouth",
"value": "Clean Smile"
},
{
"trait_type": "Eyes",
"value": "Not Okay"
},
{
"trait_type": "Hat",
"value": "Bucket Hat"
},
{
"trait_type": "Clothes",
"value": "Plaid Jacket"
},
{
"trait_type": "Eyewear",
"value": "Plastic Glasses"
}
],
"description": "Not Okay Bears Solana is an NFT project for mental health awareness. 10k collection on the Polygon blockchain. We are not okay."
}
I need to add an object to attributes.
How to do this?
My JSON classes:
public class Attribute
{
public string trait_type { get; set; }
public string value { get; set; }
}
public class Root
{
public string name { get; set; }
public string image { get; set; }
public List<Attribute> attributes { get; set; }
public string description { get; set; }
}
try this, in this case you don't need any classes
var jsonObject = JObject.Parse(json);
JObject obj = new JObject();
obj.Add("trait_type", "type");
obj.Add("value", "value");
((JArray)jsonObject["attributes"]).Add(obj);
var newJson=jsonObject.ToString();
but if you need the data not a json , you can use this code
Root data = JsonConvert.DeserializeObject<Root>(json);
data.attributes.Add(new Attribute { trait_type="type", value="value"});

Is it possible to create Avro schema for Dictionary object

Trying to implement avro serialization and deserialization in .net for kafka messages. Message model as follows.
public class SampleMessage
{
public string Hash{ get; set; }
public string FileName { get; set; }
public string Data { get; set; }
public Dictionary<string, string> Content { get; set; }
public string LineDetails { get; set; }
}
So, Is it possible to create Avro schema for Dictionary in c#?
Yes. For that, you should use the complex type "map" (https://avro.apache.org/docs/current/spec.html#Maps
Maps use the type name "map" and support one attribute:
values: the schema of the map's values.
Map keys are assumed to be strings.
Given the example, your .avsc would look something like this:
{
"type": "record",
"name": "SampleMessage",
"namespace": "samplemessage",
"fields": [
{
"name": "hash",
"type": "string"
},
{
"name": "fileName",
"type": "string"
},
{
"name": "data",
"type": "string"
},
{
"name": "content",
"type": {
"type": "map",
"values": "string"
}
},
{
"name": "lineDetails",
"type": "string"
}
]
}

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

Cannot deserialize JSON object in C#

I'm trying to deserialize the following JSON string in C#:
{
"class": [
"collection",
"Request"
],
"properties": {
"total_hits": 61,
"total_pages": 61,
"previous_page": null,
"next_page": 2,
"current_page": 1,
"per_page": 1,
"params": {
"limit": "1",
"client_ids": "1001",
"is_open": "true"
}
},
"entities": [
{
"class": [
"object",
"Request"
],
"rel": "/rels/request",
"href": "/app/requests/745109",
"properties": {
"id": 745109,
"name": "Sidewalk/Curb Repair - 628128",
"description": "651032 STrevino - We live on a corner lot. The sidewalks have become increasingly uneven over time, causing standing water at multiple places on the sidewalks. This also often creates standing mud on the sidewalk particularly after rain.\r\n\r\nCould you please request that they be leveled back to be smooth and even and allow for proper drainage?\r\n\r\nThank Very Much,\r\nAllan Meyer\r\n281-380-7012",
"created_at": "2015-02-24T02:21:41.000Z",
"updated_at": "2016-05-06T14:14:53.684Z",
"creator_id": 1110277,
"permissions": "This is visible to Sugar Land",
"comments_count": 12,
"is_current_user_commenter": false,
"follows_count": 1,
"is_current_user_following": false,
"flags_count": 0,
"is_current_user_flagger": false,
"tags_count": 0,
"average_rating": 0,
"ratings_count": null,
"object_fields": [
{
"id": 7096,
"name": "Subdivision (if applicable)",
"description": "",
"created_at": "2015-08-20T01:26:43.441Z",
"updated_at": "2015-08-20T01:26:43.441Z",
"creator_id": null,
"permissions": "This is visible to Everyone",
"display_id": 7096,
"foreign_ids": [],
"klass": "RequestType",
"data_type": "STRING",
"is_allow_null": false,
"render_guide": "TEXT",
"default_value": null,
"default_permissions": {
"read": [
707318
],
"write": [
707318
]
},
"object_field_options": []
},
{
"id": 7097,
"name": "Your Street Number and Street Name (if different location)",
"description": "",
"created_at": "2015-08-20T01:26:43.466Z",
"updated_at": "2015-08-20T01:26:43.466Z",
"creator_id": null,
"permissions": "This is visible to Everyone",
"display_id": 7097,
"foreign_ids": [],
"klass": "RequestType",
"data_type": "STRING",
"is_allow_null": true,
"render_guide": "TEXT",
"default_value": null,
"default_permissions": {
"read": [
707318
],
"write": [
707318
]
},
"object_field_options": []
},
{
"id": 7095,
"name": "Your Contact Number",
"description": "",
"created_at": "2015-08-20T01:26:43.420Z",
"updated_at": "2015-08-20T01:26:43.420Z",
"creator_id": null,
"permissions": "This is visible to Everyone",
"display_id": 7095,
"foreign_ids": [],
"klass": "RequestType",
"data_type": "STRING",
"is_allow_null": false,
"render_guide": "TEXT",
"default_value": null,
"default_permissions": {
"read": [
707318
],
"write": [
707318
]
},
"object_field_options": []
},
{
"id": 7094,
"name": "Your Name",
"description": "",
"created_at": "2015-08-20T01:26:43.395Z",
"updated_at": "2015-08-20T01:26:43.395Z",
"creator_id": null,
"permissions": "This is visible to Everyone",
"display_id": 7094,
"foreign_ids": [],
"klass": "RequestType",
"data_type": "STRING",
"is_allow_null": false,
"render_guide": "TEXT",
"default_value": null,
"default_permissions": {
"read": [
707318
],
"write": [
707318
]
},
"object_field_options": []
}
],
"object_field_instances": [
{
"id": 702607,
"name": null,
"description": null,
"created_at": "2015-02-24T13:12:15.000Z",
"updated_at": "2015-08-20T04:14:39.720Z",
"permissions": "This is visible to Sugar Land",
"value": "Magnolia Plantation",
"object_field_id": 7096
},
{
"id": 702606,
"name": null,
"description": null,
"created_at": "2015-02-24T13:12:15.000Z",
"updated_at": "2015-08-20T04:14:39.702Z",
"permissions": "This is visible to Sugar Land",
"value": "2811 Grassy Knoll Ct.",
"object_field_id": 7097
},
{
"id": 702605,
"name": null,
"description": null,
"created_at": "2015-02-24T13:12:15.000Z",
"updated_at": "2015-08-20T04:14:39.682Z",
"permissions": "This is visible to Sugar Land",
"value": "281-380-7012",
"object_field_id": 7095
},
{
"id": 702604,
"name": null,
"description": null,
"created_at": "2015-02-24T13:12:15.000Z",
"updated_at": "2015-08-20T04:14:39.664Z",
"permissions": "This is visible to Sugar Land",
"value": "Allan Meyer",
"object_field_id": 7094
}
],
"display_id": 745109,
"foreign_ids": [],
"status": "IN_PROGRESS",
"priority": "MEDIUM",
"request_type_id": 29119,
"geo_location_id": 686866,
"workflow_node_id": 890541,
"workflow_graph_id": 706096,
"completed_at": "2015-02-25T16:13:17.000Z",
"due_at": "2016-05-10T05:00:00.000Z",
"due_status": "OPEN",
"client_id": 1001,
"display_foreign_id": false,
"api_source_id": 15,
"is_duplicate": false,
"is_self_closure_allowed": true,
"has_duplicates": false,
"use_permission_matrix": true,
"request_type_foreign_api_ids": [],
"primary_attachment_id": null,
"attachments_count": 0,
"primary_attachment": null,
"contact_info": {
"name": "Allan Meyer",
"full_name": "Allan Meyer",
"first_name": "Allan",
"last_name": "Meyer",
"username": "allanrmeyer",
"phone": "",
"email": "allanrmeyer#gmail.com",
"user_id": 1110277
},
"geo_location": {
"id": 686866,
"name": "2811 Grassy Knoll Court, Sugar Land, TX 77478, USA",
"description": null,
"created_at": "2015-08-20T04:06:13.717Z",
"updated_at": "2015-08-20T04:06:13.717Z",
"creator_id": null,
"permissions": "This is visible to Everyone",
"geo_data_id": 738892,
"postal_address_id": 682944,
"accuracy_m": null,
"latitude": 29.585971,
"longitude": -95.587433,
"geo_location": {},
"postal_address": {
"id": 682944,
"name": "2811 Grassy Knoll Court, Sugar Land, TX 77478, USA",
"description": "2811 Grassy Knoll Court, Sugar Land, TX 77478, USA",
"created_at": "2015-08-20T04:06:13.706Z",
"updated_at": "2015-08-20T04:06:13.706Z",
"permissions": "This is visible to Everyone",
"source": null,
"street_number": "2811",
"street_number_unit": null,
"street_name": "Grassy Knoll Court",
"postal_code": "77478",
"region_id": 17622,
"geo_data_id": null,
"intersection": null,
"formatted_address": "2811 Grassy Knoll Court"
}
},
"request_type_name": "Sidewalk/Curb Repair",
"creator_display_name": "Allan Meyer",
"api_source_name": "Iframe"
},
"actions": []
}
],
"actions": [],
"links": [
{
"rel": [
"self"
],
"href": "/app/requests?page=1&limit=1&sort_dir=asc&client_ids=1001&is_open=true"
},
{
"rel": [
"next"
],
"href": "/app/requests?page=2&limit=1&sort_dir=asc&client_ids=1001&is_open=true"
}
]
}
I've created the following RootObject class to map the JSON:
public class RootObject
{
public List<string> #class { get; set; }
public Properties2 properties { get; set; }
public List<Entity> entities { get; set; }
public List<object> actions { get; set; }
public List<Link> links { get; set; }
}
Previously the following code was working to deserialize the JSON into the RootObject:
var objResponse1 = JsonConvert.DeserializeObject<RootObject>(response2.Content);
However, my code is now throwing a JSON.net exception:
An unhandled exception of type
'Newtonsoft.Json.JsonSerializationException' occurred in
Newtonsoft.Json.dll
Additional information: Cannot deserialize the current JSON object
(e.g. {"name":"value"}) into type
'System.Collections.Generic.List`1[ProcessOpenRequests.Program+RootObject]'
because the type requires a JSON array (e.g. [1,2,3]) to deserialize
correctly.
To fix this error either change the JSON to a JSON array (e.g.
[1,2,3]) or change the deserialized type so that it is a normal .NET
type (e.g. not a primitive type like integer, not a collection type
like an array or List) that can be deserialized from a JSON object.
JsonObjectAttribute can also be added to the type to force it to
deserialize from a JSON object.
Now, I have tried the following to deserialize the JSON string based on other StackOverflow posts in regards to this error but the error has persisted:
var test = JsonConvert.DeserializeObject<List<RootObject>>(response2.Content);
Any help would be greatly appreciated. Thanks!
*Updated
Here is the Entity class:
public class Entity
{
public List<string> #class { get; set; }
public string rel { get; set; }
public Properties2 properties { get; set; }
public Actions actions { get; set; }
}
And here is the Properties2 class:
public class Properties2
{
public int? id { get; set; }
public string name { get; set; }
public string description { get; set; }
public string created_at { get; set; }
public string updated_at { get; set; }
public int? creator_id { get; set; }
public string permissions { get; set; }
public int? comments_count { get; set; }
public bool is_current_user_commenter { get; set; }
public int? follows_count { get; set; }
public bool is_current_user_following { get; set; }
public int? flags_count { get; set; }
public bool is_current_user_flagger { get; set; }
public int? tags_count { get; set; }
public decimal average_rating { get; set; }
public object ratings_count { get; set; }
public List<ObjectField> object_fields { get; set; }
public List<ObjectFieldInstance> object_field_instances { get; set; }
public int? display_id { get; set; }
public List<object> foreign_ids { get; set; }
public string status { get; set; }
public string priority { get; set; }
public int? request_type_id { get; set; }
public int? geo_location_id { get; set; }
public int? workflow_node_id { get; set; }
public int? workflow_graph_id { get; set; }
public object completed_at { get; set; }
public string due_at { get; set; }
public string due_status { get; set; }
public int? client_id { get; set; }
public bool display_foreign_id { get; set; }
public int? api_source_id { get; set; }
public bool is_duplicate { get; set; }
public bool is_self_closure_allowed { get; set; }
public bool has_duplicates { get; set; }
public bool use_permission_matrix { get; set; }
public List<object> request_type_foreign_api_ids { get; set; }
public object primary_attachment_id { get; set; }
public int? attachments_count { get; set; }
public object primary_attachment { get; set; }
public ContactInfo contact_info { get; set; }
public GeoLocation geo_location { get; set; }
public string request_type_name { get; set; }
public string creator_display_name { get; set; }
public string api_source_name { get; set; }
}
You are trying to deserialize your JSON into a List<RootObject>. That requires your JSON to be an array, but your JSON is not an array, JSON arrays begin and end with [ and ].
Try desalinizing to a RootObject instead.
var test = JsonConvert.DeserializeObject<RootObject>(response2.Content);
So, here's what happened, the API I was receiving the JSON data from changed up the RootObject and where I was previously referencing Properties2, I needed to change that to reference Properites. I also had to change a bunch of integers to now receive null data. My original code to deserialize the RootObject (and Bruno Garcia's answer) is valid once again.

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; }

Categories

Resources