Json Deserialize in C# - c#

How to use JsonConvert.DeserializeObject with below Json
[{
"attributes" : {
"type" : "User",
"url" : "/xx/xx/xx"
},
"Id" : "1",
"Name" : "abc"
},{
"attributes" : {
"type" : "User",
"url" : "/xx/xx/xx"
},
"Id" : "2",
"Name" : "abc"
},{
"attributes" : {
"type" : "User",
"url" : "/xx/xx/xx"
},
"Id" : "3",
"Name" : "abc"
}]
These are my class
public class Attributes
{
public string type { get; set; }
public string url { get; set; }
}
public class RootObject
{
public Attributes attributes { get; set; }
public string Id { get; set; }
public string Name { get; set; }
}
I have tried with
var c = JsonConvert.DeserializeObject <RootObject>(jsonText);

Your Json actually represents an array of RootObject instances. Try this:
var c = JsonConvert.DeserializeObject<RootObject[]>(jsonText);
Or possibly
var c = JsonConvert.DeserializeObject<List<RootObject>>(jsonText);
Or even
var c = JsonConvert.DeserializeObject<IEnumerable<RootObject>>(jsonText);

Your JSON is actually an array, so try deserializing it into RootObject[]:
var c = JsonConvert.DeserializeObject<RootObject[]>(jsonText);

You json is a array (or collection), try to deserialize it using the array type:
var c = JsonConvert.DeserializeObject<RootObject[]>(jsonText);
Or any other type of collection, for sample:
var c = JsonConvert.DeserializeObject<IEnumerable<RootObject>>(jsonText);
var c = JsonConvert.DeserializeObject<ICollection<RootObject>>(jsonText);

Try telling the deserializer what you're expecting to deserialize to, in this case RootObject.
According to the documentation of the method you're currently calling JsonConvert.DeserializeObject Method (String) returns a .net object.
While this method JsonConvert.DeserializeObject<T> Method (String) returns the specified type.
for example:
public class Attributes
{
public string type { get; set; }
public string url { get; set; }
}
public class RootObject
{
public Attributes attributes { get; set; }
public string Id { get; set; }
public string Name { get; set; }
}
RootObject c = JsonConvert.DeserializeObject<RootObject>(jsonText);

Related

Inconsistent JSON

I am trying to parse JSON in C# which is inconsistent, i.e
Below are the example of JSON that I am getting.
{
"Timestamp" : "2019-05-09T11:24:25.000Z",
"Channel" : "web",
"Supplier" : "kunde",
"Generator" : "survey",
"Type" : "hudtest",
"Data" :{
"Alder" : "20-29",
"Køn" : "Kvinde",
"Hudtype" : "sensitiv",
"Hudtilstand" : "mixet"
}
}
and variation of this JSON is like this:
{
"Timestamp" : "2019-05-09T11:24:25.000Z",
"Channel" : "web",
"Supplier" : "kunde",
"Generator" : "survey",
"Type" : "hudtest",
"Data" :{
"Alder" : "20-29",
"Køn" : "Kvinde",
"Hudtype" : "sensitiv",
"Hudtilstand" : "mixet",
"materialistID" : 61234,
  "Anbefalede produkter" : [ 100225, 725125 ]
}
}
As you can see in both example I have different values in Data key. How can I parse this JSON in C#?
FYI: The Data key can have different value from the example i shared above. Not only "Anbefalede produkter. It can contain number of different values.
I have tried making it dynamic or parsing into anonymous type as well. But I also want to validate my JSON schema, Except Data Key other keys must be validated and they are mandatory.
You can do like this
class Program
{
static void Main(string[] args)
{
string jsonData = #"{ 'Timestamp': '2019-05-09T11:24:25.000Z',
'Channel': 'web',
'Supplier': 'kunde',
'Generator': 'survey',
'Type': 'hudtest',
'Data': {
'Alder': '20-29',
'Køn': 'Kvinde',
'Hudtype': 'sensitiv',
'Hudtilstand': 'mixet',
'materialistID': 61234,
'Anbefalede produkter': [100225, 725125]
}
}";
var b = JsonConvert.DeserializeObject<Rootobject>(jsonData);
//Console.WriteLine(b.Data.Hudtype);
//or
Console.WriteLine(b.Data["Hudtype"]);
Console.ReadKey();
}
}
public class Rootobject
{
public DateTime Timestamp { get; set; }
public string Channel { get; set; }
public string Supplier { get; set; }
public string Generator { get; set; }
public string Type { get; set; }
public Dictionary<string, object> Data { get; set; }
}
Hope this will solve your problem.
Thanks

De serialization of object is giving error : Cannot deserialize the current JSON object?

I am calling sales force api to get search result. For connecting to sales force i am using force client.
var client = GetForceClient(token);
string query = "FIND {01} IN ALL FIELDS RETURNING CASE(Id,Account.Name,Case_Id__c,Customer_Ticket_Id__c,Site__r.Name,Order__r.Name,Site__r.Country__c,Status,Subject LIMIT 5 OFFSET 0),Order__c(Order_Name__c,Tech_Service_Type__C,Customer__r.Name,End_Customer__r.Name,Site__r.Site_Name__c,name LIMIT 5 OFFSET 0),SITE__C(ID,Status__c,Address__c,Site_Name__c,NAME)";
var response = await client.SearchAsync<Search>(query);
when the result is being deserialized in this line
var response = await client.SearchAsync<Search>(query);
The following error is being thrown.
Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[API.Dto.Search]' 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<T>) 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.
Path 'searchRecords', line 1, position 17.
The json response looks like this
{
"searchRecords" : [ {
"attributes" : {
"type" : "Case",
"url" : "/services/data/v43.0/sobjects/Case/5000D"
},
"Id" : "5000D",
"Account" : {
"attributes" : {
"type" : "Account",
"url" : "/services/data/v43.0/sobjects/Account/0010"
},
"Name" : "AAPTxxvvbb"
},
"Case_Id__c" : "CLIC-0001234",
"Customer_Ticket_Id__c" : "33FWQ23",
"Site__r" : null,
"Order__r" : {
"attributes" : {
"type" : "Order__c",
"url" : "/services/data/v43.0/sobjects/Order__c/a060D"
},
"Name" : "ORD-602"
},
"Status" : "Open",
"Subject" : "Please Provide Your Reference"
}, {
"attributes" : {
"type" : "Order__c",
"url" : "/services/data/v43.0/sobjects/Order__c/a060D"
},
"Order_Name__c" : "Bro 2K",
"Tech_Service_Type__c" : "Bro",
"Customer__r" : {
"attributes" : {
"type" : "Account",
"url" : "/services/data/v43.0/sobjects/Account/0010"
},
"Name" : "XT"
},
"End_Customer__r" : {
"attributes" : {
"type" : "Account",
"url" : "/services/data/v43.0/sobjects/Account/0010"
},
"Name" : "Ran"
},
"Site__r" : {
"attributes" : {
"type" : "Site__c",
"url" : "/services/data/v43.0/sobjects/Site__c/a0A0"
},
"Site_Name__c" : "Ran01"
},
"Name" : "ORD-6025"
}, {
"attributes" : {
"type" : "Site__c",
"url" : "/services/data/v43.0/sobjects/Site__c/a0A0"
},
"Id" : "a0A0",
"Status__c" : "In Progress",
"Address__c" : "Rue",
"Site_Name__c" : "Ran01",
"Name" : "SIT-0154"
} ]
}
The Equivalent C# class is this :
public class Search
{
[JsonProperty("searchRecords")]
public SearchRecord[] SearchRecords { get; set; }
}
public class SearchRecord
{
[JsonProperty("attributes")]
public Attributes Attributes { get; set; }
[JsonProperty("Id", NullValueHandling = NullValueHandling.Ignore)]
public string Id { get; set; }
[JsonProperty("Account", NullValueHandling = NullValueHandling.Ignore)]
public Account Account { get; set; }
[JsonProperty("Case_Id__c", NullValueHandling = NullValueHandling.Ignore)]
public string CaseIdC { get; set; }
[JsonProperty("Customer_Ticket_Id__c", NullValueHandling = NullValueHandling.Ignore)]
public string CustomerTicketIdC { get; set; }
[JsonProperty("Site__r", NullValueHandling = NullValueHandling.Ignore)]
public SiteR SiteR { get; set; }
[JsonProperty("Order__r", NullValueHandling = NullValueHandling.Ignore)]
public Account OrderR { get; set; }
[JsonProperty("Status", NullValueHandling = NullValueHandling.Ignore)]
public string Status { get; set; }
[JsonProperty("Subject", NullValueHandling = NullValueHandling.Ignore)]
public string Subject { get; set; }
[JsonProperty("Order_Name__c", NullValueHandling = NullValueHandling.Ignore)]
public string OrderNameC { get; set; }
[JsonProperty("Tech_Service_Type__c", NullValueHandling = NullValueHandling.Ignore)]
public string TechServiceTypeC { get; set; }
[JsonProperty("Customer__r", NullValueHandling = NullValueHandling.Ignore)]
public Account CustomerR { get; set; }
[JsonProperty("End_Customer__r", NullValueHandling = NullValueHandling.Ignore)]
public Account EndCustomerR { get; set; }
[JsonProperty("Name", NullValueHandling = NullValueHandling.Ignore)]
public string Name { get; set; }
[JsonProperty("Status__c")]
public object StatusC { get; set; }
[JsonProperty("Address__c")]
public string AddressC { get; set; }
[JsonProperty("Site_Name__c", NullValueHandling = NullValueHandling.Ignore)]
public string SiteNameC { get; set; }
}
public partial class Attributes
{
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("url")]
public string Url { get; set; }
}
I have searched a lot for this but not able to figure out what is wrong.
The problem is caused by how the SearchAsync method of the ForceClient deserializes the response.
The client attempts to deserialize the response from the server as a List<T> but, as we see in the JSON, the response is wrapped in a searchRecords element first so the deserialization throws the exception you are seeing.
To get around this you need to do the following:
Change the SearchAsync call to use a dynamic type:
var response = await client.SearchAsync<dynamic>(query);
Deserialize the searchRecords property of the new type into an array of SearchRecord
var records = JsonConvert.DeserializeObject<List<SearchRecord>>(list.searchRecords.ToString());
You can now use the records variable to read the data returned from the API call.
NOTE
For reference, I looked at the source on GitHub, found how the SearchAsync method worked and then looked at the tests to find out how they were retrieving data from the SearchAsync call. The unit test code that showed me the answer is here

Parse single values from HttpResponse

In making a call to the Google Geolocation API, the results (json) are returned like so
Example (Apologies, I couldn't get the Json to format properly)
{"geocoded_waypoints" : [
{
"geocoder_status" : "OK",
"place_id" : "EiQ3LCA3IExha2VzaWRlIERyLCBSeWUsIE5ZIDEwNTgwLCBVU0EiHRobChYKFAoSCQH00P0vl8KJEQ2d7mWAl0jrEgE3",
"types" : [ "subpremise" ]
},
{
"geocoder_status" : "OK",
"place_id" : "ChIJ1YqpR4eRwokRTuazxMrnKiM",
"types" : [ "establishment", "point_of_interest" ]
} ],
"routes" : [{
"bounds" : {
"northeast" : {
"lat" : 41.0044903,
"lng" : -73.6892836
},
"southwest" : {
"lat" : 40.9575099,
"lng" : -73.7589093
}
},
"copyrights" : "Map data ©2018 Google",
"legs" : [
{
"distance" : {
"text" : "7.0 mi",
"value" : 11325
},
"duration" : {
"text" : "15 mins",
"value" : 889
},
"end_address" : "851 Fenimore Rd, Mamaroneck, NY 10543, USA",
"end_location" : {
"lat" : 40.9575099,
"lng" : -73.75338219999999
},
"start_address" : "7 Pheasant Run #7, Rye, NY 10580, USA",
"start_location" : {
"lat" : 40.99850199999999,
"lng" : -73.689633
},
There are various single items I need to retrieve from the returned data, for example, the duration:text value.
Is there a way to filter out the excess in the API call or how do I parse this from the Json?
I tried deserializing to an object to then iterate over it and grab the legs array, but A. that doesn't work as the object is on big item, not a collection and B. that seems wasteful.
public int TravelTimeInMinutes(string origin, string destination, string apiKey)
{
var timeToTravel = 0;
var url = DirectionsUrlBase + ConvertOriginFormat(origin) + ConvertDestinationFormat(destination) + "&key="+ apiKey;
var client = new HttpClient();
// Add the Accept type header for JSON format.
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
// get the response
// make method async once working
var response = client.GetAsync(url).Result;
if (response.IsSuccessStatusCode)
{
// Parse the response body.
var result = JsonConvert.SerializeObject(response.Content.ReadAsStringAsync().Result());
dynamic array = JsonConvert.DeserializeObject(result);
foreach (var item in array)
{
}
//… rest removed for brevity
How can I drill down to retrieve single values? I think my error is in how I am deserializing the response. I also have a Duration class with Text and Value properties. I would like to deserialize to that class if possible.
Follow up
I added .Result after the serialize call
response.Content.ReadAsStringAsync().Result()
this is now returning proper json
Now how can I parse single values from this or can I deserialize into the Duration class.
Per Charles suggestion
I have a root object
public class MapsDirectionObject
{
public GeocodedWaypoints[] geocoded_waypoints { get; set; }
public Routes[] routes { get; set; }
}
public class Routes
{
public object[] Value { get; set; }
}
public class GeocodedWaypoints
{
public string geocoder_status { get; set; }
public string place_id { get; set; }
public string[] types { get; set; }
}
And since the returned json only has two main children, routes and waypoints, I have those classes as well. The deserialization errors with the following error.
Newtonsoft.Json.JsonSerializationException: 'Error converting value "{ "geocoded_waypoints" : [
{
If I remove the .Result call on the serialization, I can map to that object but the values are null.
first of all I'd prefer we do strongly typed deserialization, so let's create classes corresponding to the data we need from the JSON:
public class ResultData
{
[JsonProperty("routes")]
public List<Route> Routes { get; set; }
}
public class Route
{
[JsonProperty("legs")]
public List<Leg> Legs { get; set; }
}
public class Leg
{
[JsonProperty("duration")]
public Duration Duration { get; set; }
}
public class Duration
{
[JsonProperty("text")]
public string Text { get; set; }
[JsonProperty("value")]
public int Value { get; set; }
}
then we deserialize the JSON:
var client = new HttpClient();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = client.GetAsync("https://maps.googleapis.com/maps/api/directions/json?origin=7+7+Lakeside+Dr+Rye+NY&destination=Winged+Winged+Foot+Golf+Club").Result;
if (response.IsSuccessStatusCode)
{
var desed = JsonConvert.DeserializeObject<ResultData>(response.Content.ReadAsStringAsync().Result);
var durations = desed.Routes.SelectMany(r => r.Legs.Select(l => l.Duration)).ToList();
durations.ForEach(d => Console.WriteLine($"T: {d.Text}, V: {d.Value}"));
}
Note:
skip the serialization step ... ReadAsStringAsync() should produce a valid JSON string
First of all, please post a complete valid JSON object on your answer.
You uses Visual Studio for coding right? You can use Paste Special for help you:
1) Copy your entire JSON to clipboard;
2) Open your class file on Visual Studio;
3) Go to menu "Edit > Paste Special > Paste as JSON Class";
4) You will got something like this:
public class Rootobject
{
public Geocoded_Waypoints[] geocoded_waypoints { get; set; }
}
public class Geocoded_Waypoints
{
public string geocoder_status { get; set; }
public string place_id { get; set; }
public string[] types { get; set; }
}
Now you can deserialize to a typed object:
var myObject = JsonConvert.DeserializeObject<Rootobject>(result);
foreact(var geocoded_waypoints in myObject.geocoded_waypoints)
{
// do something with geocoded_waypoints
}
// your duration object:
var duration = myObject.routes[0].legs[0].duration;
If you want you can rename Rootobject to any name you want, like Geolocation.

xamarin c# deserialize Json containing nested object

I have a webservice that return a Json in this format :
[{
"Route0": {
"RouteID": "AAA",
"RouteDescription": "",
"ReturnCode": "0",
"ReturnError": ""
}
}, {
"Route1": {
"RouteID": "AABCLO",
"RouteDescription": "Antoine Abdo Bachaalani Close",
"ReturnCode": "0",
"ReturnError": ""
}
}]
I need to deserialize it:
I created 2 class:
public class PullRouteDetailsObjectChild
{
public string RouteID { get; set; }
public string RouteDescription { get; set; }
public string ReturnCode { get; set; }
public string ReturnError { get; set; }
}
public class PullRouteDetailsObject
{
public PullRouteDetailsObjectChild Route { get; set; }
}
and I am using this code to deserialize:
List<PullRouteDetailsObject> jsonRoutes =
JsonConvert.DeserializeObject<List<PullRouteDetailsObject>>(jsonresult);
I am able to get a list of 2 PullRouteDetailsObject wich is correct but the child object is always null.
I am sure that I am missing something but can't find what. I need to access child object
Thank you for your help.
You need to use this instead:
var jsonRoutes = JsonConvert.DeserializeObject<List<Dictionary<string, PullRouteDetailsObject>>>(jsonresult);
As you're getting a list of objects with a property which contains your 'PullRouteDetailsObject' (Route0, Route1).

Null exception on nested JSON object

I'm using Newtonsoft to deserialize an array of JSON objects. I'm able to successfully deserialize the entire object with the exception of the fully nested #attributes objects.
Here is a snippet of an item I'm trying to parse:
"item" : [{
"title" : "Bloody.Birthday.1981.1080p.BluRay.X264-7SinS",
"guid" : "https:\/\/api.nzb.su\/details\/35e799ce66c3290db629b68e3bac20f9",
"link" : "https://",
"comments" : "https://url",
"pubDate" : "Wed, 25 Jun 2014 12:47:16 -0400",
"category" : "Movies > HD",
"description" : "Bloody.Birthday.1981.1080p.BluRay.X264-7SinS",
"enclosure" : {
"#attributes" : {
"url" : "https://url",
"length" : "6777211483",
"type" : "application\/x-nzb"
}
},
"attr" : [{
"#attributes" : {
"name" : "category",
"value" : "2000"
}
}, {
"#attributes" : {
"name" : "category",
"value" : "2040"
}
}, {
"#attributes" : {
"name" : "size",
"value" : "6777211483"
}
}
]
}
]
Here are my classes to drill down and populate the items:
public class item
{
public string title { get; set; }
public string pubDate { get; set; }
public IList<Attr> attr { get; set; }
}
public class Attr
{
public Attributes attribs { get; set; }
}
public class Attributes
{
public string name { get; set; }
public string value { get; set; }
}
When do I a count on the item.attr, I get the proper # but if I try to actually get the name/value of the Attributes in the list, it gives me a null error. I've done a lot of research and have been unable to determine why it's creating the appropriate items in the List but not the values within the item.
Any thoughts?
Since #attributes is not a valid property name in C#, you need to use a [JsonProperty] attribute to map it to the JSON, e.g.:
public class Attr
{
[JsonProperty("#attributes")]
public Attributes attribs { get; set; }
}

Categories

Resources