Related
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; }
}
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"
}
]
}
I hope someone can help me out here, because I'm pretty stuck ;)
I do not understand the error I'm getting:
Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'OdosTest.OdosRecord' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
Isn't my json respone (see in the bottom) okay?
I'm trying to deserialize my IRestResponse to a object, but with no luck. The classes should be finde, or where am I wrong?
Here is my code:
using System;
using RestSharp;
using Newtonsoft.Json;
using System.Collections.Generic;
namespace OdosTest
{
class Program
{
static void Main(string[] args)
{
var client = new RestClient("https://triscan.odosolutions.com/api/v1/streams");
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Basic HIDDEN");
IRestResponse response = client.Execute(request);
var odosRecord = JsonConvert.DeserializeObject<OdosRecord>(response.Content);
//Console.WriteLine(response.Content);
}
}
public class OdosRecord
{
public int version { get; set; }
public string id { get; set; }
public int loggerImei { get; set; }
public string vin { get; set; }
public DateTime startTime { get; set; }
public Signal[] signals { get; set; }
}
public class Signal
{
public string source { get; set; }
public string name { get; set; }
public string displayName { get; set; }
public string number { get; set; }
public string unit { get; set; }
public bool isNumericComplement { get; set; }
public Value[] values { get; set; }
}
public class Value
{
public DateTime timestamp { get; set; }
public string value { get; set; }
}
}
Here is the response I get:
[
{
"version": 1,
"id": "0414bafa-39fe-4924-a1e3-f2180161f058",
"loggerImei": 1000606,
"vin": "WF0VXXGCEVFY08396",
"startTime": "2020-07-03T12:59:04.000345Z",
"signals": [
{
"source": "OBD",
"name": "01_42_CMV",
"displayName": "CMV",
"number": "0142",
"unit": "V",
"isNumericComplement": false,
"values": [
{
"timestamp": "2020-07-03T12:59:04Z",
"value": "13.78"
}
]
},
{
"source": "OBD",
"name": "DETECTED_PROTOCOL",
"displayName": "DETECTED_PROTOCOL",
"number": "N/A",
"unit": "",
"isNumericComplement": false,
"values": [
{
"timestamp": "2020-07-03T12:59:04Z",
"value": "CAN"
}
]
},
{
"source": "OBD",
"name": "01_31_TravelledDistSinceCodeCleared",
"displayName": "TravelledDistSinceCodeCleared",
"number": "0131",
"unit": "km",
"isNumericComplement": false,
"values": [
{
"timestamp": "2020-07-03T12:59:04Z",
"value": "53749"
}
]
}
]
}
]
Your json contains a List<OdosRecord>, so this should solve the issue:
var odosRecord = JsonConvert.DeserializeObject<List<OdosRecord>>(response.Content);
otherwise you cloud change your json to this (if you are able to change the contract):
{
"version": 1,
"id": "0414bafa-39fe-4924-a1e3-f2180161f058",
"loggerImei": 1000606,
"vin": "WF0VXXGCEVFY08396",
"startTime": "2020-07-03T12:59:04.000345Z",
"signals": [
{
"source": "OBD",
"name": "01_42_CMV",
"displayName": "CMV",
"number": "0142",
"unit": "V",
"isNumericComplement": false,
"values": [
{
"timestamp": "2020-07-03T12:59:04Z",
"value": "13.78"
}
]
},
{
"source": "OBD",
"name": "DETECTED_PROTOCOL",
"displayName": "DETECTED_PROTOCOL",
"number": "N/A",
"unit": "",
"isNumericComplement": false,
"values": [
{
"timestamp": "2020-07-03T12:59:04Z",
"value": "CAN"
}
]
},
{
"source": "OBD",
"name": "01_31_TravelledDistSinceCodeCleared",
"displayName": "TravelledDistSinceCodeCleared",
"number": "0131",
"unit": "km",
"isNumericComplement": false,
"values": [
{
"timestamp": "2020-07-03T12:59:04Z",
"value": "53749"
}
]
}
]
}
I'm trying to figure out how to create a C# class that I can deserialize this json into.
Can somebody point me in the right direction?
Here is my json
{
"0": {
"heading": "Home",
"link": "#",
"dropdown": {}
},
"1": {
"heading": "About",
"link": "#",
"dropdown": {
"0": {
"name": "Programs",
"value": "programs"
},
"1": {
"name": "Sample Page",
"value": "test"
},
"2": {
"name": "Donations",
"value": "donations"
}
}
},
"2": {
"heading": "Products",
"link": "#",
"dropdown": {}
},
"3": {
"heading": "Contact Us",
"link": "#",
"dropdown": {
"0": {
"name": "Programs",
"value": "programs"
},
"1": {
"name": "Donations",
"value": "donations"
}
}
}
}
I've tried the following, with no luck
public class Menu
{
public MenuItem MenuItems { get; set; }
}
public class MenuItem
{
public string Heading { get; set; }
public string Link { get; set; }
public DropDownMenu DropDownMenu { get; set; }
}
public class DropDownMenu
{
public string Name { get; set; }
public string Value { get; set; }
}
In my controller I'm using the following to try and deserialize the json into my object.
[HttpPost]
public ActionResult AddMenu(string menuType, string menu, string menuTitle)
{
var serializer = new JavaScriptSerializer();
var newMenu = serializer.Deserialize<Menu>(menu);
}
Note: The menu variable contains the JSON string.
Your current JSON has 4 menu items in it... I am guessing that could change to 5 or 6, right?... if so... your JSON is incorrect, you should use an array.
Something like:
[
{
"heading": "Home",
"link": "#",
"dropdown": []
},
{
"heading": "About",
"link": "#",
"dropdown": [
{
"name": "Programs",
"value": "programs"
},
{
"name": "Sample Page",
"value": "test"
},
{
"name": "Donations",
"value": "donations"
}
]
},
{
"heading": "Products",
"link": "#",
"dropdown": []
},
{
"heading": "Contact Us",
"link": "#",
"dropdown": [
{
"name": "Programs",
"value": "programs"
},
{
"name": "Donations",
"value": "donations"
}
]
}
]
And then define your class:
public class MenuItem
{
public string heading
{
get;
set;
}
public string link
{
get;
set;
}
public DropDownMenu[] dropdown
{
get;
set;
}
}
public class DropDownMenu
{
public string Name
{
get;
set;
}
public string Value
{
get;
set;
}
}
Then you can deserialize your JSON as an "Array of MenuItems"... like:
var ser = new JavaScriptSerializer();
var newMenu = ser.Deserialize<MenuItem[]>(json);
Hope that helps,
Daniel.
From ScottGu's blog:
ASP.NET MVC 3 includes built-in JSON binding support that enables
action methods to receive JSON-encoded data and model-bind it to
action method parameters.
Instead of receiving the parameter as string you could try binding the request directly to your object (json model binding):
[HttpPost]
public ActionResult AddMenu(string menuType, Menu menu, string menuTitle)
{
// use menu here, no need to deserialize anything else
}
Also, make sure the client sends the request's content type as json, for example:
contentType: 'application/json; charset=utf-8',
See Phil Haack's example
Here and here are two more.
I am trying to deserialize the following JSON, but I really have no idea how to use JSON.net to do the work. I am using C# and JSON.Net library.
My JSON is as follows:
{
"found": 3,
"bounds": [
[
-43.54919,
172.62148
],
[
-43.54487,
172.63654
]
],
"features": [
{
"id": 15342454,
"centroid": {
"type": "POINT",
"coordinates": [
-43.54779,
172.62148
]
},
"bounds": [
[
-43.54779,
172.62148
],
[
-43.54779,
172.62148
]
],
"properties": {
"osm_element": "node",
"amenity": "toilets",
"synthesized_name": "Toilets",
"osm_id": "502884303"
},
"geometry": {
"type": "POINT",
"coordinates": [
-43.54779,
172.62148
]
},
"location": {
"county": "Canterbury",
"country": "New Zealand",
"road": "Sommerset Crescent",
"city": "Christchurch"
},
"type": "Feature"
},
{
"id": 19313858,
"centroid": {
"type": "POINT",
"coordinates": [
-43.54919,
172.63654
]
},
"bounds": [
[
-43.54919,
172.63654
],
[
-43.54919,
172.63654
]
],
"properties": {
"osm_element": "node",
"amenity": "toilets",
"synthesized_name": "Toilets",
"osm_id": "676225633"
},
"geometry": {
"type": "POINT",
"coordinates": [
-43.54919,
172.63654
]
},
"location": {
"county": "Canterbury",
"country": "New Zealand",
"road": "Colombo Street",
"city": "Christchurch"
},
"type": "Feature"
},
{
"id": 22536275,
"centroid": {
"type": "POINT",
"coordinates": [
-43.54487,
172.63632
]
},
"bounds": [
[
-43.54487,
172.63632
],
[
-43.54487,
172.63632
]
],
"properties": {
"osm_element": "node",
"amenity": "toilets",
"synthesized_name": "Toilets",
"osm_id": "864392689"
},
"geometry": {
"type": "POINT",
"coordinates": [
-43.54487,
172.63632
]
},
"location": {
"county": "Canterbury",
"country": "New Zealand",
"road": "Wordsworth Street",
"city": "Christchurch"
},
"type": "Feature"
}
],
"type": "FeatureCollection",
"crs": {
"type": "EPSG",
"properties": {
"code": 4326,
"coordinate_order": [
0,
1
]
}
}
}
You don't have to declare many tiny classes to deserialize. Just make use of dynamic.
Here is a working example
string jsonstr = #"{""found"": 3, ""bounds"": [[-43.54919, 172.62148], [-43.54487, 172.63654]], ""features"": [{""id"": 15342454,""centroid"": {""type"":""POINT"",""coordinates"":[-43.54779, 172.62148]},""bounds"": [[-43.54779, 172.62148], [-43.54779, 172.62148]],""properties"": {""osm_element"": ""node"", ""amenity"": ""toilets"", ""synthesized_name"": ""Toilets"", ""osm_id"": ""502884303""},""geometry"": {""type"":""POINT"",""coordinates"":[-43.54779, 172.62148]},""location"": {""county"": ""Canterbury"", ""country"": ""New Zealand"", ""road"": ""Sommerset Crescent"", ""city"": ""Christchurch""},""type"": ""Feature""},{""id"": 19313858,""centroid"": {""type"":""POINT"",""coordinates"":[-43.54919, 172.63654]},""bounds"": [[-43.54919, 172.63654], [-43.54919, 172.63654]],""properties"": {""osm_element"": ""node"", ""amenity"": ""toilets"", ""synthesized_name"": ""Toilets"", ""osm_id"": ""676225633""},""geometry"": {""type"":""POINT"",""coordinates"":[-43.54919, 172.63654]},""location"": {""county"": ""Canterbury"", ""country"": ""New Zealand"", ""road"": ""Colombo Street"", ""city"": ""Christchurch""},""type"": ""Feature""},{""id"": 22536275,""centroid"": {""type"":""POINT"",""coordinates"":[-43.54487, 172.63632]},""bounds"": [[-43.54487, 172.63632], [-43.54487, 172.63632]],""properties"": {""osm_element"": ""node"", ""amenity"": ""toilets"", ""synthesized_name"": ""Toilets"", ""osm_id"": ""864392689""},""geometry"": {""type"":""POINT"",""coordinates"":[-43.54487, 172.63632]},""location"": {""county"": ""Canterbury"", ""country"": ""New Zealand"", ""road"": ""Wordsworth Street"", ""city"": ""Christchurch""},""type"": ""Feature""}], ""type"": ""FeatureCollection"", ""crs"": {""type"": ""EPSG"", ""properties"": {""code"": 4326, ""coordinate_order"": [0, 1]}}}";
dynamic json = JsonConvert.DeserializeObject(jsonstr);
foreach (var feature in json.features)
{
Console.Write("{0},{1} - {2},{3} : ",
feature.bounds[0][0], feature.bounds[0][1],
feature.bounds[1][0], feature.bounds[1][1]);
Console.WriteLine("{0} {1} {2} {3}",
feature.location.country, feature.location.county, feature.location.city, feature.location.road);
}
Non-dynamic version
JObject json = (JObject)JsonConvert.DeserializeObject(jsonstr);
foreach (var feature in json["features"])
{
Console.Write("{0},{1} - {2},{3} : ",
feature["bounds"][0][0], feature["bounds"][0][1],
feature["bounds"][1][0], feature["bounds"][1][1]);
Console.WriteLine("{0} {1} {2} {3}",
feature["location"]["country"], feature["location"]["county"], feature["location"]["city"], feature["location"]["road"]);
}
public class Centroid
{
public string type { get; set; }
public List<double> coordinates { get; set; }
}
public class Properties
{
public string osm_element { get; set; }
public string amenity { get; set; }
public string synthesized_name { get; set; }
public string osm_id { get; set; }
}
public class Geometry
{
public string type { get; set; }
public List<double> coordinates { get; set; }
}
public class Location
{
public string county { get; set; }
public string country { get; set; }
public string road { get; set; }
public string city { get; set; }
}
public class Feature
{
public int id { get; set; }
public Centroid centroid { get; set; }
public List<List<double>> bounds { get; set; }
public Properties properties { get; set; }
public Geometry geometry { get; set; }
public Location location { get; set; }
public string type { get; set; }
}
public class Properties2
{
public int code { get; set; }
public List<int> coordinate_order { get; set; }
}
public class Crs
{
public string type { get; set; }
public Properties2 properties { get; set; }
}
public class RootObject
{
public int found { get; set; }
public List<List<double>> bounds { get; set; }
public List<Feature> features { get; set; }
public string type { get; set; }
public Crs crs { get; set; }
}
Here you go.
There is a tool for generating C# classes from json http://json2csharp.com/.
First create a class that fits the JSONed object.
Then, simply write JsonConvert.DeserializeObject<ClassName>(json)
Where ClassName is the name of your class and json is a string containing you JSON.
You have quite a complex data structure, so creating a class for it might be a bit complex.
You might want to maybe simplify it a little bit.
How I would tackle this....
First take your JSON and paste it into: http://jsonviewer.stack.hu/ - this gives you a view like:
Now, from the objects shown in that view create a class for each type of object - e.g:
public class MainWrapper
{
public int found {get;set;}
public List<Bound> bounds {get;set;}
public List<Feature> features {get;set;}
public Crs crs {get;set;
}
Finally you can now use some Newtonsoft to deserialize as: JsonConvert.DeserializeObject<MainWrapper>(text)