I am trying to get data from a Mixpanel API. The JSON result looks like this:
{"computed_at": "2019-11-19T10:36:33.908802+00:00", "legend_size": 1, "data": {"series": ["2019-11-11", "2019-11-12", "2019-11-13"], "values": {"page views": {"2019-11-12": 111, "2019-11-11": 573, "2019-11-13": 209}}}}
I am struggling with nested JSON (despite looking at a fair few StackOverflow articles on this) and I want to try and get the values 111,573 and 209 for the page views. How do I access these values?
I've tried the following:
var result = {"computed_at": "2019-11-19T10:36:33.908802+00:00", "legend_size": 1, "data": {"series": ["2019-11-11", "2019-11-12", "2019-11-13"], "values": {"page views": {"2019-11-12": 111, "2019-11-11": 573, "2019-11-13": 209}}}}
var rawData = result["data"]["values"]["page views"][0]
but this doesn't work and I can't figure out how to access the individual values. Can anyone help please?
EDIT:
When using the json to C# converter (as suggested in the comments to this post) the outcome is as follows:
public class PageViews
{
public int __invalid_name__2019-11-20 { get; set; }
public int __invalid_name__2019-11-19 { get; set; }
}
public class Values
{
public PageViews __invalid_name__page views { get; set; }
}
public class Data
{
public List<string> series { get; set; }
public Values values { get; set; }
}
public class RootObject
{
public DateTime computed_at { get; set; }
public int legend_size { get; set; }
public Data data { get; set; }
}
and I am still unsure how to get the numbers from this?
There are two approaches you could take. First, I'd deserialize the json string using this library - Newtonsoft.
You can then go through the json using JObjects, or you can create a C#-Class that represents your json data and then deserialize it into a corresponding object.
Via a class:
To create the json class there is this website, which creates the classes (also nested) just as the json needs them to be: http://json2csharp.com/
Then you use:
var myObject = JsonConvert.DeserializeObject<MyClass>(jsonString);
and then simply go through your object properties.
Via JObject
JObjects allow you to search through the json string easily as such:
JObject myObject = JObject.Parse(json);
var results = myObject["data"]["values"]["page views"].First();
Edit:
Since your Json contains keys, which begin with a number (and are not valid c# variable names) its a bit more tricky but doable. The automatic converter failed on this.
string json = "{\"computed_at\": \"2019 - 11 - 19T10: 36:33.908802 + 00:00\", \"legend_size\": 1, \"data\": {\"series\": [\"2019 - 11 - 11\", \"2019 - 11 - 12\", \"2019 - 11 - 13\"], \"values\": {\"page views\": {\"2019 - 11 - 12\": 111, \"2019 - 11 - 11\": 573, \"2019 - 11 - 13\": 209}}}}";
var myObject = JsonConvert.DeserializeObject<RootObject>(json);
foreach (var view in myObject.data.series)
{
int number = myObject.data.values.page_views[view];
Console.WriteLine($"{number} views on {view}");
}
With the RootObject class being:
public class Values
{
[JsonProperty("page views")]
public Dictionary<string, int> page_views { get; set; }
}
public class Data
{
public List<string> series { get; set; }
public Values values { get; set; }
}
public class RootObject
{
public string computed_at { get; set; }
public int legend_size { get; set; }
public Data data { get; set; }
}
The trick was to use a Dictionary<string, int> type for the date-values, and rename the property to a valid c# name. The JsonDeserializer still finds the data, because we told it to look for "page views" using the JsonProperty attribute. This way the class is also flexible for multiple entries in your "page views" field.
Hope this helps
You were close. In the line
var rawData = result["data"]["values"]["page views"][0]
you are attempting to access index 0 of an object. This doesn't really make sense because objects are basically dictionaries or hash tables, which means they are unordered and must be accessed by a key rather than an index (See Retrieving a property of a JSON object by index?).
What you want looks like
var rawData = result["data"]["values"]["page views"]['2019-11-12'] to access the number of page views (which is 111) for the date 2019-11-12.
You can then loop through the object and get each number of page views as follows:
var pageViews = [];
for (var key of Object.keys(result.data.values['page views'])) {
pageViews.push(result.data.values['page views'][key]);
}
Related
I am new to C# and have investigated without success. I come from programming in PHP and I have the following JSON:
{"data": [
{ "iD":0 , "name":"woody", "a":4.0, "b": 3.5, "foo": [5,8] },
{ "iD":1 , "name":"donald", "a":5.0, "b": 2.4, "foo": [4, 2] }
]}
What I need is to create something similar in C#, if possible in a separate class to be able to access the data in the correct way.
I tried to create a different array for each item but I think it is not correct.
From what I've researched, based on the JSON I've presented as an example, I have the following data types: "string, int and double".
In PHP you can mix this type of data in the same array and call it through indexes but I don't know exactly how to do the same in C #.
Eye, my question is not how to read the JSON that I have put above, but how to create an similar array (or an object) with that data structure and that I can access it from another class.
I hope I was clear, thanks in advance.
You should create classes/structs to represent this data's structure:
public class Datum {
public int ID { get; set; }
public string Name { get; set; }
public double A { get; set; }
public double B { get; set; }
public List<int> C { get; set; }
}
You can either store this Datum directly in a List<Datum>, or like you have done in the JSON, store it in another class as a property named Data:
public class RootObject {
public List<Datum> Data { get; set; }
}
Then, you can create these objects using object and collection initialisers:
var rootObject = new RootObject {
Data = new List<Datum> {
new Datum {
ID = 0,
Name = "Woody",
A = 4.0,
B = 3.5,
C = new List<int> { 5, 8 }
},
new Datum {
...
}
}
}
I can parse up to one nested level but I'm unable to figure out how to read the data in the consumption_history. I have been trying different ways to do it but could not get the consumption value.
I can access the miu_id and meter_number but not the array of consumption_list.
Model:
class JsonModel
{
public class Rootobject
{
public string site_id { get; set; }
public Endpoint[] endpoints { get; set; }
public Paging paging { get; set; }
}
public class Paging
{
public int page { get; set; }
public int limit { get; set; }
public int total { get; set; }
public string next { get; set; }
public object prev { get; set; }
public string self { get; set; }
}
public class Endpoint
{
public string miu_id { get; set; }
public string meter_number { get; set; }
public Consumption_History[] consumption_hist { get; set; }
}
public class Consumption_History
{
public DateTime reading_date { get; set; }
public float consumption { get; set; }
public float consumption_with_multiplier { get; set; }
}
}
Program:
static void Main(string[] args)
{
string json = File.ReadAllText(#"C:\Users\ConsoleApp3\apidataone.json");
var results = JsonConvert.DeserializeObject<JsonModel.Rootobject>(json);
JsonModel.Rootobject rootobject = JsonConvert.DeserializeObject<JsonModel.Rootobject>(json);
rootobject.endpoints = JsonConvert.DeserializeObject<JsonModel.Rootobject>(json).endpoints;
foreach (JsonModel.Consumption_History ch in rootobject.endpoints)
{
Console.WriteLine(ch.consumption);
}
}
json data:
{
"site_id":"1",
"endpoints":
[{
"miu_id":"111",
"meter_number":"88",
"consumption_history":
[{
"reading_date":"2010-02-17T00:00:00",
"consumption":1.0,
"consumption_with_multiplier":1.0
}]
}]
}
I have simplified the code a bit, instead of reading from a file I have just put the JSON content in place. This code uses Newtonsoft.Json (available via NUGET package), but the way it works is the same for other serializers.
// using Newtonsoft.Json;
void Main()
{
string json = #"{
'site_id':'1',
'endpoints':
[{
'miu_id':'111',
'meter_number':'88',
'consumption_history':
[{
'reading_date':'2010-02-17T00:00:00',
'consumption':1.0,
'consumption_with_multiplier':1.0
}]
}]
}";
dynamic j = JsonConvert.DeserializeObject<dynamic>(json);
string site_id = j["site_id"].ToString();
var endpoints = j["endpoints"];
foreach (var endpoint in endpoints)
{
string miu_id = endpoint["miu_id"];
miu_id.Dump();
// ...
var consumption_histories = endpoint["consumption_history"];
foreach(var consumption in consumption_histories)
{
string reading_date = consumption["reading_date"];
reading_date.Dump();
// ...
} // foreach
} // foreach
}
Run it in .NET fiddle
Regarding JSON: Whenever there is a [ ... ] in the JSON structure, this means there is an array ({ ... } stands for an object) - and [{ ... }] is an object inside an array; both properties and array elements are separated by comma (,); strings and property names need to be enclosed in single quotes ('...'). Value assignments are done with a colon (:). In JSON, you have either objects, strings or numeric data - these are the only types existing. If you need types, you have to cast properties into the proper types by yourself.
You can access the array either via indexer (like endpoints[i] inside a for loop), or - as I am assuming - you want to go through every element, in that case a foreach loop is easier.
Note: To use it in a for loop (like for (int i = 0; i < endpointsLength; i++) { ... }), you would have to cast endpoints and consumption_histories into an array type (e.g. via var endpoints = (object[])j["endpoints"];) and lose the simplicity dynamic provides (for example, then you would need an indexer to access a property like (endpoints[i])["miu_id"] to be able to get the value of miu_id).
The keyword dynamic simplifies things a lot in this case, this way you can keep the "JavaScript-Style" of the C# code (remember JSON comes from the JavaScript world).
If you want to introduce the classes you have declared in C#, this is also possible. For example:
foreach (Consumption_History consumption in consumption_histories)
{
string reading_date = consumption.reading_date.ToString();
reading_date.Dump();
// ...
} // foreach
You can see, that reading_date is now being accessed as C# property, and because it is of type DateTime, you need to cast it into a string first. This conversion needs to be done before the foreach loop, so you can either change the data type in your class to string to avoid that, or you can use the original code shown above and copy + convert the data into typed versions of your objects (for converting a string into DateTime, you can check this out).
If you rely on the built-in conversion NewtonSoft.JSON provides, you can simply use JsonConvert.DeserializeObject<Rootobject>(json) instead of JsonConvert.DeserializeObject<dynamic>(json). Note that implicit conversions can throw exceptions.
Also, make sure that the property names in C# and in your JSON file match exactly - if not you can decorate them in C# using attributes (see here for a description how to do that) - xdtTransform found that it is not matching for consumption_hist, and mentioned it in the comments.
So I have the following task - I need to deserialize an array of Jason objects which is stored in a recourse folder in my application.
So far I have accessed the recourse and stored it into a var:
var jsonData = Resources.SamplePoints;
Converted the array into a string:
string jsonObjts = Encoding.Default.GetString(jsonData);
And have tried to write the result into a list of Dictionaries
List<Dictionary<string, double>> EntityData = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Dictionary<string, double>>>(jsonObjts);
However the above error message shows up when I run and test the application.
Can anyone please set me on the right path how to fix this?
A sample of the objects in question:
"samples": [
{
"date": "2014-08-10T09:00:00Z",
"temperature": 10,
"pH": 4,
"phosphate": 4,
"chloride": 4,
"nitrate": 10
},
{
"date": "2014-08-12T09:05:00Z",
"temperature": 10.5,
"pH": 5,
"chloride": 4,
"phosphate": 4
},
Is there a reason you don't want to create a class to represent your JSON?
public class Rootobject
{
public List<Sample> Samples { get; set; }
}
public class Sample
{
public DateTime Date { get; set; }
public float Temperature { get; set; }
public int Ph { get; set; }
public int Phosphate { get; set; }
public int Chloride { get; set; }
public int Nitrate { get; set; }
}
then you can deserialize:
var obj = JsonConvert.DeserializeObject<Rootobject>(json);
If you still want to use a Dictionary, I think you need something like this:
var obj = JsonConvert.DeserializeObject<Dictionary<string, List<Dictionary<string, object>>>>(json);
Your schema in generic type List<Dictionary<string, double>> and schema of json does not match. If you want to cast to List<Dictionary you can't use "samples": [ For this you'll need Dictionary<string,List<Dictionary.
Also when you are trying to use double, date won't get parsed to double. So maybe you can try Dictionary<string, List<Dictionary<string, object>>>. Ideally you should create class for this structure instead of using generic List, Dictionary structure.If you are using visual studio, you can create these classes by using Edit->Paste special-> paste json as classes
i am a newbie to coding , I have a nested json coming from a external source the json format is looks something like this ..
{
"data":"data",
"data":
{
"data":"data",
//----------------e.t.c the internal objects could be in n number
}
}
so how do i deserialize the json object and use the data as a list in order to do my other operations like sql and posting the data??
You need to create a class that is appropriate with the Json, like that:
public someClass
{
public string data1 { get; set; }
public DataClass dataArr { get; set; }
}
public DataClass
{
public string insideData { get; set; }
}
after you do this you need the following code:
var jsonDto = JsonConvert.DeserializeObject<someClass>(yourJson);
This is a JSON message I get from server (which I can't change). There might be many more objects (time / value) returned, but in this case there is only one. The format stays the same regardless.
{
"data": [
{
"time": "2014-12-12T13:52:43",
"value": 255.0
}
]
}
I'm trying to deserialize the JSON to a very simple C# object.
public class Dataentry {
public float Value { get; set; }
public DateTime Time { get; set; }
}
I've tried deserialization with Newtonsoft's JSON.Net and RestSharp libraries with no success. The following code doesn't work, but neither does anything else I've tried :-) I get no error -- just an empty object with default initial values.
var myObject = JsonConvert.DeserializeObject<Dataentry> (jsonString);
Since those libraries are not very intuitive or well documented in this kind of case, I'm lost. Is this kind of JSON impossible to deserialize? I really would like to use a ready-made library, so any help would be appreciated.
This is not working because your JSON is specifying a collection and you are trying to deseralize into one object. There are plenty of json to c# class generators you can paste json into to get an appropriate class definition(s) one such generator is located here
A more appropriate definition would be
public class Datum
{
public string time { get; set; }
public double value { get; set; }
}
public class RootObject
{
public List<Datum> data { get; set; }
}
Then deseralize as
var myObject = JsonConvert.DeserializeObject<RootObject> (jsonString);
I'd like add some extra explanetion to your question...
You write I'm trying to deserialize the JSON to a very simple C# object. - unfortunatelly this is not the complete truth. What you are trying is to deserialize a collection of a very simple C# objects. The indicator for this are the square brackets in your json:
{
"data": [
{
"time": "2014-12-12T13:52:43",
"value": 255.0
}
]
}
It means that there is a class with a property named data (it can ba mapped to some other name but for the sake of simplicity let's stick to this name) and that this property is a collection type. It can be one of any types that support the IEnumerable interface.
public class DataCollection
{
public DataItem[] data { get; set; }
//public List<DataItem> data { get; set; } // This would also work.
//public HashSet<DataItem> data { get; set; } // This would work too.
}
public class DataItem
{
public float value { get; set; }
public DateTime time { get; set; } // This would work because the time is in an ISO format I believe so json.net can parse it into DateTime.
}
The next step is to tell Json.Net how to deserialize it. Now when you know it's a complex data type you can use the type that describes the json structure for deserialization:
var dataCollection = JsonConvert.DeserializeObject<DataCollection>(jsonString);
If you didn't have the data property in you json string but something like this:
[
{
"time": "2014-12-12T13:52:43",
"value": 255.0
},
{
"time": "2016-12-12T13:52:43",
"value": 25.0
},
]
you could directly deserialize it as a collection:
var dataItems = JsonConvert.DeserializeObject<List<DataItem>>(jsonString);
or
var dataItems = JsonConvert.DeserializeObject<DataItem[]>(jsonString);
change your DateEntry binding Definition
public class ArrayData{
public DataEntry data {set; get;}
}
public class DataEntry {
public float Value { get; set; }
public DateTime Time { get; set; }
}
in your method now you can received an ArraData Object
be careful with datetime string values sent for correct binding