I'm trying to extract the values of "name" and "score" from the below JSON response:
"categories": [
{
"name": "people_",
"score": 0.6640625
},
{
"name": "people_portrait",
"score": 0.33203125
}
]
My current C# code to manage this is:
public class Category
{
public string name { get; set; }
public double score { get; set; }
}
...
string contentString = await response.Content.ReadAsStringAsync();
var r = JsonConvert.DeserializeObject<Category>(contentString);
Console.WriteLine(r.name);
Console.WriteLine(r.score);
Console.ReadLine();
But when I try and print the result to the console a blank response is given. I have also check the debugger and name is populated with null and score is populated with 0.
Any help with this would be much appreciated!
In json string, categories is an list of JObjects, so you can use #Roman's approach to solve your problem or try mine,
Here is my approach,
Create one root class called as Categories,
public class Categories
{
[JsonProperty(PropertyName = "categories")]
public List<Category> ListOfCategory {get; set;}
}
Your Category class,
public class Category
{
public string Name { get; set; }
public double Score { get; set; }
}
Now, deserialize using below code
var categories = JsonConvert.DeserializeObject<Categories>(contentString);
Now you can iterate though ListOfCategory,
foreach(var item in categories.ListOfCategory)
{
Console.WriteLine($"Name : {item.Name} \t Score: {item.Score}");
}
POC: .Net Fiddle
Related
I exported from Azure IoT Central to a Blob Storage a file containing several JSON objects (36 objects) within that same file.
The below are the first 2 lines from that file
{"applicationId":"appID","component":"thermostat1","deviceId":"usingTemControllerTemplate","enqueuedTime":"2022-03-21T15:31:38.687Z","enrichments":{},"messageProperties":{},"messageSource":"telemetry","schema":"default#v1","telemetry":{"temperature":23.2},"templateId":"urn:modelDefinition:tczx6jwcwz1:h2httvyo48g"}
{"applicationId":"appID","component":"thermostat2","deviceId":"usingTemControllerTemplate","enqueuedTime":"2022-03-21T15:31:38.703Z","enrichments":{},"messageProperties":{},"messageSource":"telemetry","schema":"default#v1","telemetry":{"temperature":16.9},"templateId":"urn:modelDefinition:tczx6jwcwz1:h2httvyo48g"}
I created 2 classes to show the heirarchy in the JSON objects. RootObject & Telemetry.
public class RootObject
{
public string applicationId { get; set; }
public string component { get; set; }
public string deviceId { get; set; }
public string enqueuedTime { get; set; }
public string messageSource { get; set; }
public string schema { get; set; }
public List<Telemetry> telemetry { get; set; }
public string templateId { get; set; }
}
public class Telemetry
{
public double temperature { get; set; }
}
I followed this answer and modeled it to my specific heirarchy and tried to make it work. However, a JsonReaderException is being thrown I run it in Visual Studio.
This is the code I'm running:
using Newtonsoft.Json;
string filePath = "~pathToFile";
RootObject rt = JsonConvert.DeserializeObject<RootObject>(filePath);
if (rt.telemetry[1].temperature == 23.2)
{
Console.WriteLine(rt.telemetry[1].temperature);
}
The JsonReaderException is being thrown on this line:
RootObject rt = JsonConvert.DeserializeObject<RootObject>(filePath);
In the below image is the message being shown:
Could someone please help me find the cause of this issue and how I could resolve it?
This file is not a list/array of objects, it's a 36 lines with each line containing json for a single object.
With this observation we can:
List<RootObject> list = new();
foreach(var line in lines.Where( l => !string.IsNullOrWhiteSpace(l)))
{
RootObject? o = JsonConvert.DeserializeObject<RootObject>(line);
if (o != null)
{
list.Add(o);
}
}
telmetry is an object, not a list so you need to also change the RootObject definition:
"telemetry": {
"temperature": 23.2
},
public class RootObject
{
...
public Telemetry telemetry { get; set; }
first of all the JSON format is wrong, it looks like this (see below) and
secondly he doesn't want to have the File path but the json (value), so you have to read it in
and what is also very important. You have 2 elements of "RootObject",
that means you have to put into a Array or List<> of RootObjects
Code:
using Newtonsoft.Json;
//reads the file and saves into a string
string jsonValue = File.ReadAllText("~pathToFile");
//Deserialize the objects and put them in a list of "RootObject".
List<RootObject> rt = JsonConvert.DeserializeObject<List<RootObject>>(jsonValue);
correct JSON format:
[
{
"applicationId": "appID",
"component": "thermostat1",
"deviceId": "usingTemControllerTemplate",
"enqueuedTime": "2022-03-21T15:31:38.687Z",
"enrichments": {},
"messageProperties": {},
"messageSource": "telemetry",
"schema": "default#v1",
"telemetry": {
"temperature": 23.2
},
"templateId": "urn:modelDefinition:tczx6jwcwz1:h2httvyo48g"
},
{
"applicationId": "appID",
"component": "thermostat2",
"deviceId": "usingTemControllerTemplate",
"enqueuedTime": "2022-03-21T15:31:38.703Z",
"enrichments": {},
"messageProperties": {},
"messageSource": "telemetry",
"schema": "default#v1",
"telemetry": {
"temperature": 16.9
},
"templateId": "urn:modelDefinition:tczx6jwcwz1:h2httvyo48g"
}
]
you have to fix json, by converting it to array of objects
var json = File.ReadAllText(filePath);
json = "[" + json.Replace("\n\r",",")+"]";
List<RootObject> lrt = JsonConvert.DeserializeObject<List<RootObject>>(json);
double[] telemetries=rt.Select(r => r.telemetry.temperature ).ToArray(); // [23.2,16.9]
double telemetry=rt.Where(t=> t.telemetry.temperature==23.2)
.Select(r =>r.telemetry.temperature ).FirstOrDefault(); //23.2
and fix class too, telemetry should be an object, not a list
public class RootObject
{
....
public Telemetry telemetry { get; set; }
}
I know that JsonDotNet can deserialize a json taking care of reference ids. But I couldn't find a solution for a simple array with multiple room ids assigned to a tour (in my example). I set my (de)serializer settings to:
var settings = new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects };
var data = JsonConvert.DeserializeObject<Data>(json, settings);
My model class looks like:
public class Tour
{
public string Id { get; set; }
public string Name { get; set; }
public List<Room> Rooms { get; set; }
}
public class Room
{
public string Id { get; set; }
public string Name { get; set; }
}
}
And my example json like this:
{
"tours":[
{
"$id":"luw5b23b",
"name":"Tour 1",
"rooms":[
{
"$ref":"k2j3hjh2"
},
{
"$ref":"vg2345fg"
},
{
"$ref":"nb2m5h2j"
}
]
}
],
"rooms":[
{
"$id":"k2j3hjh2",
"name":"Room 1"
},
{
"$id":"vg2345fg",
"name":"Room 2"
},
{
"$id":"nb2m5h2j",
"name":"Room 3"
}
]
}
Unfortunatelly the rooms are null. I'm a totally wrong and this is something I should process as ids and link objects after deserialization by myself or can JsonDotNet do that for me?
Please note, the object ids are provided by a system and should not generated or serialized by JsonDotNet.
I am trying to display the values of a list which is inside another list, but I am running into issues.
Here is the list containing values that I want to display:
"HotelAvailSideFilterResult": {
"listaServices": [
[
{
"code": "APCO",
"description": "Aptos./Hab. con cocina",
"font": null
},
{
So 2 things:
How do I print the description property using loops or whatever?
How do I query unique values? I tried this but repeat values are returned:
var services = resultado.Hotels.Select(h => h.Features.Distinct());//LISTA DE SERVICIOS
var hotelTypes = resultado.Hotels.Select(h => h.Type.Distinct()).Distinct();//LISTA DE TIPOS DE HOTEL
model resultadoFiltro = new model()
{
listaServices = services.ToList(),
};
Here are my models:
public IEnumerable<IEnumerable<RS.Feature>> listaServices { get; set; }
public partial class Hotel
{
public List<Feature> Features { get; set; }
}
public class Feature
{
[JsonProperty("code")]
public string Code { get; set; }
[JsonProperty("description")]
public string Description { get; set; }
[JsonProperty("font")]
public string Font { get; set; }
}
Thank you very much
Finally the best way is this:
hotelAvailRS.Hotels.SelectMany(h => h.Features).ToList().GroupBy(f => f.Code).Select(f => f.First()).ToList()
Because you will have what you need and also later you will be able to use the property Code to bind when be required.
Hope it helps!!
I have JSON like this:
{
'surveys': [
{
'title': 'first',
'id': 100,
},
{
'title': 'second',
'id': 101,
},
{
'title': 'third',
'id': 102,
},
]
}
I want to have the output like this:
title: first
title: second
title: third
and my program in C# is like this:
WebClient client = new WebClient();
var json = client.DownloadString("http://www.test.com/api/surveys/?api_key=123");
Debug.WriteLine(json); //write all data from json
//add
var example = JsonConvert.DeserializeObject<Example>(json);
Debug.WriteLine(example.Data.Length);
class Example
{
public surveys[] Data { get; set; }
}
class surveys
{
public string title { get; set; }
public int id { get; set; }
}
I get this error:
Thrown: "Object reference not set to an instance of an object." (System.NullReferenceException) Exception Message = "Object reference not set to an instance of an object.", Exception Type = "System.NullReferenceException", Exception WinRT Data = ""
at this line: Debug.WriteLine(example.Data.Length);
where is the problem?
One problem I see is that your outer class has a property named Data, which is an array of 'surveys' objects, but your Json has a list of 'surverys' objects under the property 'surveys'. Hence the 'Data' property is never populated.
Consider the following C# class structure:
class Example
{
public survey[] surveys{ get; set; }//Data renames to surveys
}
class survey //Singular
{
public string title { get; set; }
public int id { get; set; }
}
Why can't you do so?:
JObject data = JObject.Parse(json);
foreach (var survey in data["surveys"].Children())
{
Debug.WriteLine("title: " + survey["title"]);
}
You need to use JSON.Net and use the class JsonConvert and the method DeserializeObject<T>.
If you run this:
JsonConvert.DeserializeObject<JObject>();
Then you will get back a list of de-serialized JObject objects.
Use, NuGet to download the package. I think it is called JSON.net.
Here is the weblink
WebClient client = new WebClient();
var json = client.DownloadString("http://www.test.com/api/surveys/?api_key=123");
Debug.WriteLine(json); //write all data from json
//add
var example = JsonConvert.DeserializeObject<Survey>(json);
Debug.WriteLine(example.length); // this could be count() instead.
class Survey
{
public string title { get; set; }
public int id { get; set; }
}
This should work!
Use json2csharp to generate c# classes from json.
You will also need to use Json.NET.
public class Survey
{
public string title { get; set; }
public int id { get; set; }
}
public class RootObject
{
public List<Survey> surveys { get; set; }
}
Then you can do:
var client = new WebClient();
string json = client.DownloadString(some_url);
RootObject root = JsonConvert.DeserializeObject<RootObject>(json);
foreach (Survey s in root.surveys)
{
// Do something with your survey
}
Don't forget to use Newtonsoft.Json namespace once you add a reference to it within your project.
using Newtonsoft.Json;
Edit: I have tested it using:
string json = "{'surveys': [{'title': 'first','id': 100,},{'title': 'second','id': 101,},{'title': 'third','id': 102,},]}";
instead of using the WebClient, and it works.
I have the following issue with this json :
{
"EVTS": {
"EVT": [
{ "ID": "123456",
"KEY1" : "somekey",
"CATEG": [
"cat1",
"cat2",
"cat3"
]
}
]}
}
and this c# class:
public class myClass{
public string ID { get; set; }
public string KEY1 { get; set; }
public list<string> CATEG { get; set; }
}
public class ESObject1
{
[JsonProperty("EVT")]
public List<myClass> EVT { get; set; }
}
public class ESObject0
{
[JsonProperty("EVTS")]
public ESObject1 EVTS { get; set; }
}
}
here i call the deserializer :
ESObject0 globalobject = JsonConvert.DeserializeObject<ESObject0>(json);
But this last code doesnt work, i throws this exception : System.ArgumentException: Could not cast or convert from System.String to System.Collections.Generic.List1[System.String].`
Instead of list<string> i used string [] and only string nothing seems to work.
how can i deserialize this object correctly please.
Thank you.
There doesn't seem to be any apparent problem wit hyour code as this working example illustrates:
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
public class myClass
{
public string ID { get; set; }
public string KEY1 { get; set; }
public List<string> CATEG { get; set; }
}
public class ESObject1
{
[JsonProperty("EVT")]
public List<myClass> EVT { get; set; }
}
public class ESObject0
{
[JsonProperty("EVTS")]
public ESObject1 EVTS { get; set; }
}
class Program
{
static void Main()
{
string json =
#"{
""EVTS"": {
""EVT"": [
{
""ID"": ""123456"",
""KEY1"": ""somekey"",
""CATEG"": [
""cat1"",
""cat2"",
""cat3""
]
}
]
}
}";
ESObject0 globalobject = JsonConvert.DeserializeObject<ESObject0>(json);
foreach (string item in globalobject.EVTS.EVT[0].CATEG)
{
Console.WriteLine(item);
}
}
}
Maybe you just fed a wrong json value to the deserializer which doesn't look like as the one shown in your question. By the way, the one shown i nyour question is invalid JSON as you are missing a , after KEY1 property declaration.
UPDATE:
Now that you have shown your real JSON (coming from http://donnees.ville.quebec.qc.ca/Handler.ashx?id=69&f=JSON) it appears that there's a row where CATEG is not an array of strings but a simple string:
""CATEG"": ""Conférence""
Now that's a pretty bad design because they are mixing arrays and simple properties. I am afraid that in order to deal with this situation you will need to use JObjects and extract the information you need by testing the actual underlying type.
For example:
var obj = JObject.Parse(json);
var events = (JArray)obj["EVTS"]["EVT"];
foreach (JObject evt in events)
{
var categories = evt["CATEG"];
if (categories is JArray)
{
// you've got a list of strings so you can loop through them
string[] cats = ((JArray)categories)
.Select(x => x.Value<string>())
.ToArray();
}
else
{
// you've got a simple string
string cat = categories.Value<string>();
}
}
I have done this many times with many many headaches. My advice is take the json output and use a tool similar to this to write your class for you (http://json2csharp.com/).
Then go over any nullable variables and add nullable type (ex. using int? for int) where needed.