Inconsistent JSON - c#

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

Related

Create corresponding Model for JSON string to get specific value in C#

I have an API that returns a JSON string and I want to parse that JSON string into an object. I tried creating the object but with no luck. Below is the sample JSON string that I want to get the value from. Any idea as to what the class looks like in order to parse that JSON object into an object? My main concern is to get the code which is "platinum" under currentCard.
{
"status" : {
"currentCard" : {
"code" : "platinum"
},
"status" : {
"index" : 0,
"value" : "This is a sample text."
}
}
}
You need to use a website such as https://json2csharp.com/ or use the inbuilt tools in VS Studio (Edit->Paste Special->Paste JSON as classes) which will automatically create classes from JSON.
The above mentioned website suggests the following:
public class CurrentCard
{
public string code { get; set; }
}
public class Status2
{
public int index { get; set; }
public string value { get; set; }
public CurrentCard currentCard { get; set; }
public Status status { get; set; }
}
public class Root
{
public Status status { get; set; }
}
Which you can then deserialise like this:
Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(myJsonResponse);

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
}

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

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