How will I get this json into my c# class - c#

I would like to read in a json respons to my c# class for learning and having problem with it.
This is the main code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.IO;
using Newtonsoft.Json;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
var webClient = new System.Net.WebClient();
var json = webClient.DownloadString("https://api.trafiklab.se/samtrafiken/resrobotstops/GetDepartures.json?key=[KEY]&apiVersion=2.2&locationId=7420752&coordSys=RT90");
This url will return this json
{"getdeparturesresult":{"departuresegment":[{"departure":{"location":
{"#id":"7420752","#x":"1271307","#y":"6404493","name":"Göteborg Brunnsparken"}
,"datetime":"2014-12-10 12:27"},"direction":"Göteborg Kålltorp","segmentid":
{"mot":{"#displaytype":"S","#type":"SLT","#text":"Spårvagn"},"carrier":
{"name":"Västtrafik","url":"http:\/\/www.vasttrafik.se\/","id":"279","number":"3"}}},
The first problem is that when generating a c# class it will complain about the # in the variable name. How can this be fixed? I mean I cant change the json respons. That is what I get. My guess would be this:
getdeparturesresult.departuresegment.departure.location["#x"]);
The second is how will I write to get it in to my class? What should be used?
I have tried this but then it will complain about my RootObject:
string json = r.ReadToEnd();
List<RootObject> items = JsonConvert.DeserializeObject<List<RootObject>>(json);
Lets say I got a class like this
public class Location
{
public string id { get; set; }
public string x { get; set; }
public string y { get; set; }
public string name { get; set; }
}
public class Departure
{
public Location location { get; set; }
public string datetime { get; set; }
}
public class Mot
{
public string displaytype { get; set; }
public string type { get; set; }
public string text { get; set; }
}
public class Carrier
{
public string name { get; set; }
public string url { get; set; }
public string id { get; set; }
public string number { get; set; }
}
public class Segmentid
{
public Mot mot { get; set; }
public Carrier carrier { get; set; }
}
public class Departuresegment
{
public Departure departure { get; set; }
public string direction { get; set; }
public Segmentid segmentid { get; set; }
}
public class Getdeparturesresult
{
public Departuresegment departuresegment { get; set; }
}
public class RootObject
{
public Getdeparturesresult getdeparturesresult { get; set; }
}
I have also tried this
dynamic array = JsonConvert.DeserializeObject(json);
foreach (var item in array)
{
Console.WriteLine("{0}", item);
}
This will printout whats in the json. But how do I get it to be read into my class? I cant figure it out. It must be simple but I cant get it right.

You only need to change like:
public class Getdeparturesresult
{
public IEnumerable<Departuresegment> departuresegment { get; set; }
}
You can still use the Json.net serializer (JsonConvert).
Edit:
To handle the "#id" property you can do this:
[JsonProperty("#id")]
public string id { get; set; }

You could accomplish that with JavaScriptSerializer.
var root = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<RootObject>(json);
It worked for me, but I had to change the type of Getdeparturesresult.departuresegment property to an array:
public class Getdeparturesresult
{
public Departuresegment[] departuresegment { get; set; }
}
Update:
To deserialize JSON properties with special characters with .NET, you can use DataContractJsonSerializer.
RootObject root;
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(json)))
root = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(RootObject)).ReadObject(stream) as RootObject;
But your code will have to get verbose. You need to mark every class with [DataContract] and every property with [DataMember] attributes. For the properties whose names are not equal to those of the source, use [DataMember(Name = "#fancy_name")].
[DataContract]
public class Location
{
[DataMember(Name = "#id")]
public string id { get; set; }
[DataMember(Name = "#x")]
public string x { get; set; }
[DataMember(Name = "#y")]
public string y { get; set; }
[DataMember]
public string name { get; set; }
}
// etc.

Related

Unable to correctly parse JSON body

I am successfully able to retrieve the JSON body from a URL in Visual Studio 2019 using Newtonsoft library. However I'm having difficulty in parsing out the only variable I am interested in.
I've tried to follow some guides on here that I don't seem to have either implemented correctly or haven't fully understood (I'm pretty new to this).
e.g.
Unexpected character encountered while parsing API response
RAW JSON:
{"deviceId":37,"longMacAddress":"5884e40000000439","shortMacAddress":259,"hoplist":"(259,3)","associationTime":"2019-06-10 22:43:54","lifeCheckInterval":5,"lastLiveCheck":"2019-06-11 07:11:37","onlineStatus":1,"txPowerValue":14,"deviceType":1,"frequencyBand":1,"lastLivecheck":"2019-06-11 07:11:36","disassociationState":0,"firmwareUpdateActivated":0,"firmwareUpdatePackagesSent":0,"firmwareUpdatePackagesUnsent":0,"firmwareUpdateInProgress":0,"deviceIdOem":"-1","deviceNameOem":"-1","deviceCompanyOem":"-1","binaryInputCount":0,"binaryOutputCount":0,"analogInputCount":0,"characterStringCount":1,"location":[{"location":"UK","locationWriteable":1,"changedAt":"2019-06-10 23:40:50"}],"description":[{"description":"DevKit","descriptionWriteable":1,"changedAt":"2019-06-10 23:40:54"}],"binaryInput":[],"binaryOutput":[],"analogInput":[],"characterString":[{"characterString":"149+0.0+99+26.5+0","characterStringWriteable":1,"changedAt":"2019-06-11 06:45:02"}]}
MY MAIN CODE:
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace API_JSON_1
{
class Program
{
static void Main(string[] args)
{
var client = new WebClient();
var JSON = client.DownloadString("http://192.168.0.254:8000/nodes/longmac/5884e40000000439");
Console.WriteLine(JSON);
Console.WriteLine("----------------------------------------------");
CharacterString CSV = JsonConvert.DeserializeObject<CharacterString>(JSON);
Console.WriteLine("Sensor data: " + CSV.CharacterStringCharacterString);
}
}
}
MY CHARACTER STRING CLASS:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace API_JSON_1
{
public class CharacterStrings
{
public CharacterStrings CharString { get; set; }
}
public class CharacterString
{ public string CharacterStringCharacterString { get; set; }
public long CharacterStringWriteable { get; set; }
public DateTimeOffset ChangedAt { get; set; }
}
}
OUTPUT TO THE CONSOLE:
{"deviceId":37,"longMacAddress":"5884e40000000439","shortMacAddress":259,"hoplis
t":"(259,3)","associationTime":"2019-06-10 22:43:54","lifeCheckInterval":5,"last
LiveCheck":"2019-06-11 06:56:37","onlineStatus":1,"txPowerValue":14,"deviceType"
:1,"frequencyBand":1,"lastLivecheck":"2019-06-11 06:56:33","disassociationState"
:0,"firmwareUpdateActivated":0,"firmwareUpdatePackagesSent":0,"firmwareUpdatePac
kagesUnsent":0,"firmwareUpdateInProgress":0,"deviceIdOem":"-1","deviceNameOem":"
-1","deviceCompanyOem":"-1","binaryInputCount":0,"binaryOutputCount":0,"analogIn
putCount":0,"characterStringCount":1,"location":[{"location":"UK","locati
onWriteable":1,"changedAt":"2019-06-10 23:40:50"}],"description":[{"description"
:"DevKit","descriptionWriteable":1,"changedAt":"2019-06-10 23:40:54"}],"binaryIn
put":[],"binaryOutput":[],"analogInput":[],"characterString":[{"characterString"
:"149+0.0+99+26.5+0","characterStringWriteable":1,"changedAt":"2019-06-11 06:45:
02"}]}
----------------------------------------------
Sensor data:
Press any key to continue . . .
Obviously I was expecting/hoping that the penultimate line there would read:
"Sensor data: 149+0.0+99+26.5+0"
In order for this to work you have to modify your classes like this:
public class CharacterStrings
{
public List<CharacterStringObject> CharacterString { get; set; }
}
public class CharacterStringObject
{
public string CharacterString { get; set; }
public long CharacterStringWriteable { get; set; }
public DateTime ChangedAt { get; set; }
}
After that, after you read your JSON like that:
CharacterString CSV = JsonConvert.DeserializeObject<CharacterString>(JSON);
You end up with List<CharacterStringObject> with one element in it. So you take the first one like that and print it:
Console.WriteLine("Sensor data: " + CSV.CharacterString.First().CharacterString);
Cheers,
Edit: Tested it locally with your given JSON, works fine
Welcome to StackOverflow!
Something you need to keep in mind when converting a json string to an object (ie: Deserialize) is that the object to which you are converting the string into needs to match the format of the json string. In your case, the json string does not match the object to which you are converting.
Once you have the correct object, this will give you the output you want:
static void Main(string[] args)
{
string JSON = "{\"deviceId\":37,\"longMacAddress\":\"5884e40000000439\",\"shortMacAddress\":259,\"hoplist\":\"(259,3)\",\"associationTime\":\"2019-06-10 22:43:54\",\"lifeCheckInterval\":5,\"lastLiveCheck\":\"2019-06-11 07:11:37\",\"onlineStatus\":1,\"txPowerValue\":14,\"deviceType\":1,\"frequencyBand\":1,\"lastLivecheck\":\"2019-06-11 07:11:36\",\"disassociationState\":0,\"firmwareUpdateActivated\":0,\"firmwareUpdatePackagesSent\":0,\"firmwareUpdatePackagesUnsent\":0,\"firmwareUpdateInProgress\":0,\"deviceIdOem\":\"-1\",\"deviceNameOem\":\"-1\",\"deviceCompanyOem\":\"-1\",\"binaryInputCount\":0,\"binaryOutputCount\":0,\"analogInputCount\":0,\"characterStringCount\":1,\"location\":[{\"location\":\"UK\",\"locationWriteable\":1,\"changedAt\":\"2019-06-10 23:40:50\"}],\"description\":[{\"description\":\"DevKit\",\"descriptionWriteable\":1,\"changedAt\":\"2019-06-10 23:40:54\"}],\"binaryInput\":[],\"binaryOutput\":[],\"analogInput\":[],\"characterString\":[{\"characterString\":\"149+0.0+99+26.5+0\",\"characterStringWriteable\":1,\"changedAt\":\"2019-06-11 06:45:02\"}]}";
Console.WriteLine(JSON);
Console.WriteLine("----------------------------------------------");
RootObject CSV = JsonConvert.DeserializeObject<RootObject>(JSON);
// Option 1: Loop over the items in your List<CharacterString>...
foreach (var cs in CSV.characterString)
{
Console.WriteLine("Sensor data: " + cs.characterString);
}
// Option 2: Or, if you know there is only one in the list...
Console.WriteLine("Sensor data: " + CSV.characterString.First().characterString);
}
EDIT to explain the code above: Because characterString is a List<CharacterString>, it's technically possible that you could have more than one item in that list. Option 1: If you want, you can loop through that list to display the items in it. But if you know for certain that there will only be one item in the list, then, Option 2: You can just display the .First() item in the list.
I took the json sting you gave us, and using this handy website (http://json2csharp.com/#) I converted it into the following classes:
public class RootObject
{
public int deviceId { get; set; }
public string longMacAddress { get; set; }
public int shortMacAddress { get; set; }
public string hoplist { get; set; }
public string associationTime { get; set; }
public int lifeCheckInterval { get; set; }
public string lastLiveCheck { get; set; }
public int onlineStatus { get; set; }
public int txPowerValue { get; set; }
public int deviceType { get; set; }
public int frequencyBand { get; set; }
public string lastLivecheck { get; set; }
public int disassociationState { get; set; }
public int firmwareUpdateActivated { get; set; }
public int firmwareUpdatePackagesSent { get; set; }
public int firmwareUpdatePackagesUnsent { get; set; }
public int firmwareUpdateInProgress { get; set; }
public string deviceIdOem { get; set; }
public string deviceNameOem { get; set; }
public string deviceCompanyOem { get; set; }
public int binaryInputCount { get; set; }
public int binaryOutputCount { get; set; }
public int analogInputCount { get; set; }
public int characterStringCount { get; set; }
public List<Location> location { get; set; }
public List<Description> description { get; set; }
public List<object> binaryInput { get; set; }
public List<object> binaryOutput { get; set; }
public List<object> analogInput { get; set; }
public List<CharacterString> characterString { get; set; }
}
public class Location
{
public string location { get; set; }
public int locationWriteable { get; set; }
public string changedAt { get; set; }
}
public class Description
{
public string description { get; set; }
public int descriptionWriteable { get; set; }
public string changedAt { get; set; }
}
public class CharacterString
{
public string characterString { get; set; }
public int characterStringWriteable { get; set; }
public string changedAt { get; set; }
}
The CharacterString property in the json is an array of objects. Also the first property in those objects is characterString. Below is a working example
Output is Sensor Data: 149+0.0+99+26.5+0
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
namespace SOTest
{
class Program
{
static void Main(string[] args)
{
var json =
"{\"deviceId\":37,\"longMacAddress\":\"5884e40000000439\",\"shortMacAddress\":259,\"hoplist\":\"(259,3)\",\"associationTime\":\"2019-06-10 22:43:54\",\"lifeCheckInterval\":5,\"lastLiveCheck\":\"2019-06-11 07:11:37\",\"onlineStatus\":1,\"txPowerValue\":14,\"deviceType\":1,\"frequencyBand\":1,\"lastLivecheck\":\"2019-06-11 07:11:36\",\"disassociationState\":0,\"firmwareUpdateActivated\":0,\"firmwareUpdatePackagesSent\":0,\"firmwareUpdatePackagesUnsent\":0,\"firmwareUpdateInProgress\":0,\"deviceIdOem\":\"-1\",\"deviceNameOem\":\"-1\",\"deviceCompanyOem\":\"-1\",\"binaryInputCount\":0,\"binaryOutputCount\":0,\"analogInputCount\":0,\"characterStringCount\":1,\"location\":[{\"location\":\"UK\",\"locationWriteable\":1,\"changedAt\":\"2019-06-10 23:40:50\"}],\"description\":[{\"description\":\"DevKit\",\"descriptionWriteable\":1,\"changedAt\":\"2019-06-10 23:40:54\"}],\"binaryInput\":[],\"binaryOutput\":[],\"analogInput\":[],\"characterString\":[{\"characterString\":\"149+0.0+99+26.5+0\",\"characterStringWriteable\":1,\"changedAt\":\"2019-06-11 06:45:02\"}]}";
var obj = JsonConvert.DeserializeObject<CharacterStrings>(json);
Console.WriteLine($"Sensor Data: {obj.CharacterString.First().CharacterString}");
Console.ReadKey();
}
public class CharacterStrings
{
public List<Characters> CharacterString { get; set; }
}
public class Characters
{ public string CharacterString { get; set; }
public long CharacterStringWriteable { get; set; }
public DateTime ChangedAt { get; set; }
}
}
}
You are defining the CSV object with CharacterSting. I should be CharacterStrings and Inside the CharacterStrings class it should to be array because your JSON is an array

Convert Rest API JSON Response into C# object

I have a code REST API response which is json, and parsing to JObject and pulling a value from it. But i am getting the error when parsing to JObject.
Error: "Unexpected character encountered while parsing value: S. Path '', line 0, position 0."
Is there any other way to convert Json string to C# object.
I have the following code:
using Newtonsoft.Json;
using (HttpResponseMessage message = httpclient.GetAsync(folderIdURL).Result)
{
if(message.IsSuccessStatusCode)
{
var dataobjects = message.Content.ReadAsStringAsync();
//dataobjects = "{"id":"https://gbc-dev5.cloud.wc.com/DctmRest/repositories/dmgbsap_crt/","title":"DQL query results","author":[{"name":"EMC Documentum"}],"updated":"2019-05-02T15:19:52.508+00:00","page":1,"items-per-page":100,"links":[{"rel":"self","href":"https://gbc-dev5.cloud.wc.com/DctmRest/repositories/dmgbsap_crt/?dql=SELECT%20r_object_id%2cobject_name%20FROM%20dm_sysobject%20WHERE%20FOLDER%20(%27%2fgbc%2fUS%2fOSA-ATTACHMENT%2f2019%27)"}],"entries":[{"id":"https://gbc-dev5.cloud.wc.com/DctmRest/repositories/dmgbsap_crt/?dql=SELECT%20r_object_id%2cobject_name%20FROM%20dm_sysobject%20WHERE%20FOLDER%20(%27%2fgbc%2fUS%2fOSA-ATTACHMENT%2f2019%27)&index=0","title":"0b0111738011c114","updated":"2019-05-02T15:19:52.508+00:00","published":"2019-05-02T15:19:52.508+00:00","links":[{"rel":"edit","href":"https://gbc-dev5.cloud.wc.com/DctmRest/repositories/dmgbsap_crt/objects/0b0111738011c114"}],"content":{"json-root":"query-result","definition":"https://gbc-dev5.cloud.wc.com/DctmRest/repositori es/dmgbsap_crt/types/dm_sysobject","properties":{"r_object_id":"0b0111738011c114","object_name":"04"},"links":[{"rel":"self","href":"https://gbc-dev5.cloud.wc.com/DctmRest/repositories/dmgbsap_crt/objects/0b0111738011c114"}]}},{"id":"https://gbc-dev5.cloud.wc.com/DctmRest/repositories/dmgbsap_crt/?dql=SELECT%20r_object_id%2cobject_name%20FROM%20dm_sysobject%20WHERE%20FOLDER%20(%27%2fgbc%2fUS%2fOSA-ATTACHMENT%2f2019%27)&index=1","title":"0b0111738011c115","updated":"2019-05-02T15:19:52.509+00:00","published":"2019-05-02T15:19:52.509+00:00","links":[{"rel":"edit","href":"https://gbc-dev5.cloud.wc.com/DctmRest/repositories/dmgbsap_crt/objects/0b0111738011c115"}],"content":{"json-root":"query-result","definition":"https://gbc-dev5.cloud.wc.com/DctmRest/repositories/dmgbsap_crt/types/dm_sysobject","properties":{"r_object_id":"0b0111738011c115","object_name":"05"},"links":[{"rel":"self","href":"https://gbc-dev5.cloud.wc.com/DctmRest/repositories/dmgbsap_crt/objects/0b0111738011c115"}]}}]}"
JObject responseObj = JObject.Parse(dataobjects.ToString());
String id = (String)responseObj["entries" -->"content"-->"properties"-->"object_name"];
}
}
}
I am expecting the value from (String)responseObject["enteries"]["content"][" properties"]["object_name"]
JObjects are a pain. You could get a sample of the JSON response and paste it into a converter like json2csharp.com. It will generate a class for you which you can then use like so:
Generated Class:
public class MyClass
{
public string SomeProperty { get; set; }
public string AnotherProperty { get; set; }
}
Usage:
if (message.IsSuccessStatusCode)
{
var deserializedObject = JsonConvert.DeserializeObject<MyClass>(response.Content.ReadAsStringAsync().Result);
Console.WriteLine(deserializedObject.SomeProperty);
}
I would suggest to follow those steps:
You need to check that your json is actually a json, because an error says it is not. You can use online tools like this
If possible, avoid JObject and generate real classes. It is not that hard if you know the structure, and you can use another online tools
Modify your code to use classes
so you will have something like:
using System;
using Newtonsoft.Json;
namespace ConsoleApp11
{
class Program
{
public class Message
{
public Enteries enteries { get; set; }
}
public class Enteries
{
public Content content { get; set; }
}
public class Content
{
public Properties properties { get; set; }
}
public class Properties
{
public string object_name { get; set; }
}
static void Main(string[] args)
{
var input = "{\"enteries\":{\"content\":{ \"properties\":{ \"object_name\":\"your value string\"}}}}";
Message msg = JsonConvert.DeserializeObject<Message>(input);
Console.WriteLine(msg?.enteries?.content?.properties?.object_name ?? "no value");
Console.ReadKey();
}
}
}
I hope it helps 😊
Thank you so much for all the help and trips. Finally i am able to get the required value from JSON string.
Here is the Final code json2csharp.com
public class Author
{
public string name { get; set; }
}
public class Link
{
public string rel { get; set; }
public string href { get; set; }
}
public class Link2
{
public string rel { get; set; }
public string href { get; set; }
}
public class Properties
{
public string r_object_id { get; set; }
public string object_name { get; set; }
}
public class Link3
{
public string rel { get; set; }
public string href { get; set; }
}
public class Content
{
public string json_root { get; set; }
public string definition { get; set; }
public Properties properties { get; set; }
public List<Link3> links { get; set; }
}
public class Entry
{
public string id { get; set; }
public string title { get; set; }
public DateTime updated { get; set; }
public DateTime published { get; set; }
public List<Link2> links { get; set; }
public Content content { get; set; }
}
public class RootObject
{
public string id { get; set; }
public string title { get; set; }
public List<Author> author { get; set; }
public DateTime updated { get; set; }
public int page { get; set; }
public int items_per_page { get; set; }
public List<Link> links { get; set; }
public List<Entry> entries { get; set; }
}
Using Newtonsoft.Json
First get the list of entries from the responseObj. Then loop each entries and use LINQ to JSON to get values by property name or index.
You can use Item[Object] index on JObject/JArray and then cast the returned JValue to the type you want
JObject responseObj = JObject.Parse(dataobjects.ToString());
// get JSON result objects into a list
IList<JToken> entries = responseObj ["entries"].Children().ToList();
foreach(JToken entry in entries)
{
string object_name = (string) entry["content"]["properties"]["object_name"];
}

JSON list converter C#

I am completely c# beginner. I am trying to convert json data in c#. I am struggling with the list. As long as I am able to convert basic methods, I have an error in that one with the list. Do you mind to give me some advice how to fix my problem?
Original JSON data
[{"data": {"Temperature": {"data": {"2018-07-04 13:05:00": 20.9224991798401}, "meta": {"units": "Celsius", "name": "Temperature", "theme": "Weather"}}}, "latest": "2018-07-04 13:05:00", "sensor_height": -999, "type": "Weather", "base_height": -999, "geom": {"coordinates": [-1.62469, 54.98274], "type": "Point"}, "active": "True", "name": "sportshall_oat", "source": {"document": null, "fancy_name": "BMS", "db_name": "Bms", "third_party": false, "web_display_name": "BMS"}}]
Main class
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
var client = new WebClient();
var text = client.DownloadString("http://uoweb1.ncl.ac.uk/api/v1/sensor/live.json?sensor_name=sportshall_oat&api_key=4dopcdjiu3wtzfl32hn94hbf5ubm3q89jbh18iaxaqdzc10nlgbebqqvxqyt3ymydi59fjnyrmuqtgtdxb1sm5msac");
Rootobject ro = JsonConvert.DeserializeObject<Rootobject>(text);
Console.WriteLine("current time = " + ro.Property1);
Class1 c1 = JsonConvert.DeserializeObject<Class1>(text);
Data data = JsonConvert.DeserializeObject<Data>(text);
Temperature temperature = JsonConvert.DeserializeObject<Temperature>(text);
Console.WriteLine("data = " + temperature.data);
Data1 d1 = JsonConvert.DeserializeObject<Data1>(text);
Meta meta = JsonConvert.DeserializeObject<Meta>(text);
Geom geom = JsonConvert.DeserializeObject<Geom>(text);
Source source = JsonConvert.DeserializeObject<Source>(text);
}
}
}
JSON data (generated by Visual studio)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp2
{
public class Rootobject
{
public Class1[] Property1 { get; set; }
}
public class Class1
{
public Data data { get; set; }
public string latest { get; set; }
public int sensor_height { get; set; }
public string type { get; set; }
public int base_height { get; set; }
public Geom geom { get; set; }
public string active { get; set; }
public string name { get; set; }
public Source source { get; set; }
}
public class Data
{
public Temperature Temperature { get; set; }
}
public class Temperature
{
public Data1 data { get; set; }
public Meta meta { get; set; }
}
public class Data1
{
public float _20180704130500 { get; set; }
}
public class Meta
{
public string units { get; set; }
public string name { get; set; }
public string theme { get; set; }
}
public class Geom
{
public float[] coordinates { get; set; }
public string type { get; set; }
}
public class Source
{
public object document { get; set; }
public string fancy_name { get; set; }
public string db_name { get; set; }
public bool third_party { get; set; }
public string web_display_name { get; set; }
}
}
When I am trying to run my program the console is crushed. After debugging I can tell where the problem is, but I don't know how to fix it. There is the error message
Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the
current JSON array (e.g. [1,2,3]) into type 'ConsoleApp2.Rootobject'
because the type requires a JSON object (e.g. {"name":"value"}) to
deserialize correctly.
To fix this error either change the JSON to a JSON object (e.g.
{"name":"value"}) or change the deserialized type to an array or a
type that implements a collection interface (e.g. ICollection, IList)
like List that can be deserialized from a JSON array.
JsonArrayAttribute can also be added to the type to force it to
deserialize from a JSON array.
Thank you all in advance.
There's a couple of problems with your code.
Since the JSON is surrounded by [...], it means it's an array or items so you need to use a List (or similar) structure. In your case, you can drop the Rootobject class completely and deserialise directly to a List<Class1>. For example:
var result = JsonConvert.DeserializeObject<List<Class1>>(json);
The Data1 class is using a date as the property name. I would suggest dropping that class completely and modify thre Temperature class to use a Dictonary<DateTime, float>:
public class Temperature
{
public Dictionary<DateTime, float> data { get; set; }
public Meta meta { get; set; }
}
And now you can cope with any DateTime being passed in, you would use it like this:
var data = obj[0].data.Temperature.data;
Console.WriteLine($"The temperature on {data.Key} was {data.Value}");
Your RootObject is wrong, and Class1 is badly named but it is essentially the right structure to deserialize the data - however the data is an array of Class1's. You can use a List<Class1> or Class1[] (array) - either should work:
var client = new WebClient();
var text = client.DownloadString("http://uoweb1.ncl.ac.uk/api/v1/sensor/live.json?sensor_name=sportshall_oat&api_key=4dopcdjiu3wtzfl32hn94hbf5ubm3q89jbh18iaxaqdzc10nlgbebqqvxqyt3ymydi59fjnyrmuqtgtdxb1sm5msac");
var result = JsonConvert.DeserializeObject<List<Class1>>(text);
You dont need to separately deserialize all the sub parts, eg you can do this:
var name = result[0].name;
(Note: your list has a single item so you need to ask the list for item with index 0, and then whatever property you're after)
I wont repeat the warning about your Temperature class, but see #DavidG's answer
Then you need a model. Based on your JSON it will result in something like this.
public class RootObject
{
public Data data { get; set; }
public DateTime latest { get; set; }
public int sensor_height { get; set; }
public string type { get; set; }
public int base_height { get; set; }
public Geom geom { get; set; }
public string active { get; set; }
public string name { get; set; }
public Source source { get; set; }
}
public class Data
{
public Temperature Temperature { get; set; }
public Meta meta { get; set; }
}
public class Geom
{
public float[] coordinates { get; set; }
public string type { get; set; }
}
public class Source
{
Public string document { get; set; }
Public string fancy_name { get; set; }
Public string db_name { get; set; }
Public string third_party { get; set; }
Public string web_display_name { get; set; }
}
public class Temperature
{
public string data { get; set; }
}
public class Meta
{
Public string units { get; set; }
Public string name { get; set; }
Public string theme { get; set; }
}
After the creation of a model you simply use this.
var result = JsonConvert.DeserializeObject<RootObject>(your_json_string);
Then you can access to the objects like this:
result.data..
result.latest...
and so on.

C# JSON Get data from List<>

I am trying to make simple UWP weather app, just for learning purpose, and I am having trouble getting data from JSON.
How to get min and max temperature from public class ConsolidatedWeather?
I can get data from other classes.
Thanks a lot
Vrime.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace _01_Weaather
{
class Vrime
{
public async static Task<ConsolidatedWeather> ShowTemp()
{
var http = new HttpClient();
var url = String.Format("https://www.metaweather.com/api/location/44418/");
var response = await http.GetAsync(url);
var result = await response.Content.ReadAsStringAsync();
var ser = new DataContractJsonSerializer(typeof(ConsolidatedWeather));
var ms = new MemoryStream(Encoding.UTF8.GetBytes(result));
var data = (ConsolidatedWeather)ser.ReadObject(ms);
return data;
}
}
[DataContract]
public class ConsolidatedWeather
{
[DataMember]
public object id { get; set; }
[DataMember]
public string weather_state_name { get; set; }
[DataMember]
public string weather_state_abbr { get; set; }
[DataMember]
public string wind_direction_compass { get; set; }
[DataMember]
public string created { get; set; }
[DataMember]
public string applicable_date { get; set; }
[DataMember]
public double min_temp { get; set; }
[DataMember]
public double max_temp { get; set; }
[DataMember]
public double the_temp { get; set; }
[DataMember]
public double wind_speed { get; set; }
[DataMember]
public double wind_direction { get; set; }
[DataMember]
public double air_pressure { get; set; }
[DataMember]
public int humidity { get; set; }
[DataMember]
public double? visibility { get; set; }
[DataMember]
public int predictability { get; set; }
}
[DataContract]
public class Parent
{
[DataMember]
public string title { get; set; }
[DataMember]
public string location_type { get; set; }
[DataMember]
public int woeid { get; set; }
[DataMember]
public string latt_long { get; set; }
}
[DataContract]
public class Source
{
[DataMember]
public string title { get; set; }
[DataMember]
public string slug { get; set; }
[DataMember]
public string url { get; set; }
[DataMember]
public int crawl_rate { get; set; }
}
[DataContract]
public class RootObject
{[DataMember]
public List<ConsolidatedWeather> consolidated_weather { get; set; }
[DataMember]
public string time { get; set; }
[DataMember]
public string sun_rise { get; set; }
[DataMember]
public string sun_set { get; set; }
[DataMember]
public string timezone_name { get; set; }
[DataMember]
public Parent parent { get; set; }
[DataMember]
public List<Source> sources { get; set; }
[DataMember]
public string title { get; set; }
[DataMember]
public string location_type { get; set; }
[DataMember]
public int woeid { get; set; }
[DataMember]
public string latt_long { get; set; }
[DataMember]
public string timezone { get; set; }
}
MainPage.xaml
namespace _01_Weaather
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
double min;
double max;
public MainPage()
{
this.InitializeComponent();
}
private async void BtnPrikaz_OnClick(object sender, RoutedEventArgs e)
{
ConsolidatedWeather cWeather = await Vrime.ShowTemp();
min =cWeather.min_temp;
max = cWeather.max_temp;
txtTemp.Text = String.Format(min.ToString() + "\n"+ max.ToString());
}
}
Your deserializing is not on the correct object. It should be on RootObject. As the JSON retured by weather API returns data for future dates as well so if you need Min and Max temperature for today then below is the sample code.
public async Task<RootObject> ShowTemp()
{
var http = new HttpClient();
var url = String.Format("https://www.metaweather.com/api/location/44418/");
var response = await http.GetAsync(url);
var result = await response.Content.ReadAsStringAsync();
var ser = new DataContractJsonSerializer(typeof(RootObject));
var ms = new MemoryStream(Encoding.UTF8.GetBytes(result));
var data = (RootObject)ser.ReadObject(ms);
return data;
}
public async Task<ConsolidatedWeather> GetWeatherForToday()
{
RootObject ro = await ShowTemp();
ConsolidatedWeather todayWeather = ro.consolidated_weather.FirstOrDefault();
return todayWeather;
// for getting min and max
// todayWeather.min_temp;
// todayWeather.max_temp;
}
try changing the data types of the attributes min & max temperature to float and you are using wrong object type to deserialize. use your root object. Also, i'd recommend using something like restsharp for api consumption. thats going to make your life 2X easier.

How do I deserialise this JSON?

I haven't done anything with JSON before... so I am probably just missing a step.
Here is an example of the JSON I want to deserialise:
{"item":{"icon":"http://services.runescape.com/m=itemdb_rs/4765_obj_sprite.gif?id=4798","icon_large":"http://services.runescape.com/m=itemdb_rs/4765_obj_big.gif?id=4798","id":4798,"type":"Ammo","typeIcon":"http://www.runescape.com/img/categories/Ammo","name":"Adamant brutal","description":"Blunt adamantite arrow...ouch","current":{"trend":"neutral","price":237},"today":{"trend":"neutral","price":0},"members":"true","day30":{"trend":"positive","change":"+1.0%"},"day90":{"trend":"negative","change":"-0.0%"},"day180":{"trend":"positive","change":"+0.0%"}}}
I put this into "Json 2 C#" and ended up creating this new .cs file:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RSTool.Models
{
public class Current
{
public string trend { get; set; }
public int price { get; set; }
}
public class Today
{
public string trend { get; set; }
public int price { get; set; }
}
public class Day30
{
public string trend { get; set; }
public string change { get; set; }
}
public class Day90
{
public string trend { get; set; }
public string change { get; set; }
}
public class Day180
{
public string trend { get; set; }
public string change { get; set; }
}
public class Item
{
public string icon { get; set; }
public string icon_large { get; set; }
public int id { get; set; }
public string type { get; set; }
public string typeIcon { get; set; }
public string name { get; set; }
public string description { get; set; }
public Current current { get; set; }
public Today today { get; set; }
public string members { get; set; }
public Day30 day30 { get; set; }
public Day90 day90 { get; set; }
public Day180 day180 { get; set; }
}
public class RootObject
{
public Item item { get; set; }
}
}
So, I have the class. I can retrieve the JSON from its location as a string, but I really have no idea how to deserialise it... I have installed Newtonsoft.Json and have tried using PopulateObject and also Deserializer but not with any luck...
Assuming that my JSON is stored as a string called "json", how would I go about storing that query and then retrieving the item name, for example?
Use:
var deserialized = JsonConvert.DeserializeObject<RootObject>(json);
I just tested this successfully given the code you supplied.
You can then access properties of object as normal:
MessageBox.Show(deserialized.item.name);

Categories