Null exception on nested JSON object - c#

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

Related

Deserializing an array of objects: The JSON value could not be converted to System.String[]

Can't access objects inside the array using JSON.Net
public class VoskReturnArray
{
public string[] result { get; set; }
public string text { get; set; }
}
var voskArray = JsonSerializer.Deserialize<VoskReturnArray>(rec.Result());
Console.WriteLine(voskArray.text); // Works fine
Console.WriteLine(voskArray.result); // Throws an exception
Tried with <List<VoskReturnArray>>, but then text won't show up.
What am I missing here?
Data:
{
"result" : [{
"conf" : 0.228337,
"end" : 0.141508,
"start" : 0.060000,
"word" : "one"
}, {
"conf" : 1.000000,
"end" : 0.390000,
"start" : 0.141508,
"word" : "hundred"
}, {
"conf" : 1.000000,
"end" : 1.080000,
"start" : 0.390000,
"word" : "employees"
}],
"text" : "one hundred employees that's where it is you know they had the same problems are those five employees companies but they have the money to pay to fix them"
}
Your data shows result as an array of objects, while your result property in VoskReturnArray model is an array of string. It should be instead an array of a model type for those objects. So rather than:
public string[] result { get; set; }
You'd want something like:
public ResultItem[] result { get; set; }
...
public class ResultItem
{
public decimal conf { get; set; }
public decimal end { get; set; }
// etc
}

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

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.

Null child data structures after JSON deserialization

I have an object that has a property which is a List of other custom objects.
It actually drills down many tiers of custom object properties, but let's just look at the last 3 levels of the object.
{
"version" : {
"version_data" : [ {
"version_value" : "6.06"
}, {
"version_value" : "7.10"
}, {
"version_value" : "8.04"
}, {
"version_value" : "8.10"
} ]
}
}
So my classes look like so:
public class Version
{
[Required()]
public Version_Data version_data { get; set; }
}
public class Version_Data
{
[MinLength(1)]
public List<Version_Data_Item> items { get; set; }
}
public class Version_Data_Item
{
[Required()]
public string version_value { get; set; }
}
I was able to extract one version_data_item
{
"version_value" : "6.06"
}
and if I deserialize that JSON I am able to call something like: deserializedObject.version_value and it returns 6.06
The problem I run into is the upper levels. For example, I then extract the "Version_Data" object from the data
{
"version_data" : [ {
"version_value" : "6.06"
}, {
"version_value" : "7.10"
}, {
"version_value" : "8.04"
}, {
"version_value" : "8.10"
} ]
}
that deserializes into a Version_Data (no exceptions raised at least), but when I debug it says the list is null.
What am I missing?
Your version_data should be called items:
{
"items" : [ {
"version_value" : "6.06"
}, {
"version_value" : "7.10"
}, {
"version_value" : "8.04"
}, {
"version_value" : "8.10"
} ]
}
For generation C# from JSON you can use very helpful web generator.
Your correct models are here:
public class VersionData
{
public string version_value { get; set; }
}
public class Version
{
public List<VersionData> version_data { get; set; }
}
public class RootObject
{
public Version version { get; set; }
}
Are you using Newtonsoft's JSON? The structure does not look correct. Unless you use custom parser, the structure should be like this:
https://app.quicktype.io?share=Olvtc5B3C1zg7hy2CJgp

Json Deserialize in 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);

Categories

Resources