I'm trying to parse the following json array
[
{
"email": "john.doe#sendgrid.com",
"timestamp": 1337197600,
"smtp-id": "<4FB4041F.6080505#sendgrid.com>",
"event": "processed"
},
{
"email": "john.doe#sendgrid.com",
"timestamp": 1337966815,
"smtp-id": "<4FBFC0DD.5040601#sendgrid.com>",
"category": "newuser",
"event": "clicked"
},
{
"email": "john.doe#sendgrid.com",
"timestamp": 1337969592,
"smtp-id": "<20120525181309.C1A9B40405B3#Example-Mac.local>",
"event": "processed"
}
]
I've not really used json format before, so it's all a little new. I found I can parse a single element easily, i.e.
{
"email": "john.doe#sendgrid.com",
"timestamp": 1337197600,
"smtp-id": "<4FB4041F.6080505#sendgrid.com>",
"event": "processed"
}
dynamic stuff = JsonConvert.DeserializeObject(json);
Response.Write(string.Format("{0} = {1}<br />", "timestamp", stuff.timestamp));
//etc
But i'm struggling with how to get the individual elements into an array to loop through.
I though about splitting the sting on },{ but didn't have much luck with that. I imagine there's an easier way i'm missing.
Thank you.
Just deserialize the JSON as is and loop it...
dynamic stuff = JsonConvert.DeserializeObject(json);
foreach (var s in stuff)
{
Console.WriteLine(s.timestamp);
}
Fiddle: http://dotnetfiddle.net/0SthDp
You can create a class like this one, to accept all properties from the json string:
public class MyClass
{
public string email { get; set; }
public long timestamp { get; set; }
[JsonProperty("smtp-id")]
public string smtpid { get; set; }
public string category { get; set; }
[JsonProperty("event")]
public string evt { get; set; }
}
As you can notice there is JsonProperty attribute on the smtpid and evt properties, because you can not use the names in the json string as properties in C#.
Then just call the following line:
var list = JsonConvert.DeserializeObject<List<MyClass>>(json);
and you'll get a strongly typed list of objects that matches the json string.
Use JSON.Net to do this for you:
Create a class to hold the data (notice the attribute I put on smtp-id to handle characters C# doesn't like):
public class EmailEvent
{
public string Email { get; set; }
public int TimeStamp { get; set; }
[Newtonsoft.Json.JsonProperty(PropertyName="smtp-id")]
public string SmtpId { get; set; }
public string Event { get; set; }
public string Category { get; set; }
}
Then just deserialize it:
var events = Newtonsoft.Json.JsonConvert.DeserializeObject<List<EmailEvent>>(System.IO.File.ReadAllText(#"z:\temp\test.json"));
foreach (var ev in events)
{
Console.WriteLine(ev.SmtpId);
}
Create these two classes to hold your data:
public class SMTPEvent {
public string Email { get; set; }
public long TimeStamp { get; set; }
public string SmtpId { get; set; }
public string EventType { get; set; }
}
public class SMTPEvents {
public List<SMTPEvent> Events { get; set; }
}
Then you can call the following:
dynamic stuff = JsonConvert.DeserializeObject<SMTPEvents>(json);
To iterate you can then use:
foreach(SMTPEvent sEvent in stuff)
{
//whatever you want to do.
}
The advantage to this approach is having more type safety at run-time whilst having reusable objects if you're going to use them in other parts of your system. If not, you might want to use the simpler dynamic approach as suggested by others.
Also, remember to use the JsonProperty attribute to specify the actual property name as specified in your JSON string if you cannot / are not going to create fields that have the exact name as in your JSON.
The first level - stuff - is an Array of objects. It is the objects, or elements in said array, which contain a timestamp field.
Consider the following:
dynamic items = JsonConvert.DeserializeObject(json);
foreach(dynamic item in items) {
/* use item.timestamp */
}
Related
I am trying to serialize JSON objects received from an API in a cli app. I'm having issues understanding how to create the objects in .NET for JSON objects which have an indented structure.
For example, this is fine:
{"status": "ok" }
public class Success
{
public string status { get; set; }
}
But something like this is where I'm stuck and both of the examples from the below return null when the client API receives them.
[
{
"id": "some_uuid_string_1",
"message": "hello"
},
{
"id": "some_uuid_string_2",
"message": "world"
}
]
Attempted solution
public class Received
{
public Dictionary<string,string> received { get; set; }
}
Alternatively I also tried a simpler structure, leaving out the explicit names and just using the IDs and values, which is closer to what my app requires and lets me make smaller requests.
{
"some_uuid_string_1": "hello",
"some_uuid_string_2": "world"
}
For this example I tried this, a list of key value pairs in the form of a dictionary.
public class Message
{
public Dictionary<string,string> message { get; set; }
}
public class Received
{
public List<Message> received { get; set; }
}
How can I create objects in C# for these two structures? One indented with set names and one 'generic' with no set names.
public class MyClass
{
public string id { get; set; }
public string message { get; set; }
}
[
{
"id": "some_uuid_string",
"message": "hello"
},
{
"id": "some_uuid_string",
"message": "world"
}
]
Deserializes to a List<MyClass> or MyClass[]
{
"some_uuid_string_1": "hello",
"some_uuid_string_2": "world"
}
Deserializes to
public class MyClass
{
public string some_uuid_string_1 { get; set; }
public string some_uuid_string_2 { get; set; }
}
or Dictionary<string, string>
The reason your Received class solution didn't work is because it is expecting a JSON property of received, as your class has a property named received, but the JSON does not.
This is the same issue with your Message class. Your class has property message whereas your JSON does not.
create a class
public class MessageId
{
public string id { get; set; }
public string message { get; set; }
}
you can deserialize your json
using Newtonsoft.Json;
var messages=JsonConvert.DeserializeObject<List<MessageId>>(yourJson);
...and "beautiful" is sarcastic here.
When you call Active Campaign's list_view endpoint, and would like to get that in a json response, then this is the json response you get:
{
"0": {
"id": "4",
"name": "Nieuwsletter 1",
"cdate": "2018-11-22 03:44:19",
"private": "0",
"userid": "6",
"subscriber_count": 2901
},
"1": {
"id": "5",
"name": "Newsletter 2",
"cdate": "2018-11-22 05:02:41",
"private": "0",
"userid": "6",
"subscriber_count": 2229
},
"2": {
"id": "6",
"name": "Newsletter 3",
"cdate": "2018-11-22 05:02:48",
"private": "0",
"userid": "6",
"subscriber_count": 638
},
"result_code": 1,
"result_message": "Success: Something is returned",
"result_output": "json"
}
Now how would I ever be able to deserialize this to an object? Doing the normal Edit => Paste Special => Paste JSON As Classes gives me an output where I end up with classes that named _2.
Also, JsonConvert throws the following error: Accessed JObject values with invalid key value: 2. Object property name expected. So it is not really able to deserialize it either. I tried to use dynamic as object type to convert to.
The only thing I can think of now is replacing the first { by [ and the last } by ], then remove all the "1" : items and then remove the last 3 properties. After that I have a basic array which is easy convertable. But I kind of hope someone has a better solution instead of diving deep into the string.indexOf and string.Replace party...
If your key/value pair is not fixed and data must be configurable then Newtonsoft.json has one feature that to be used here and that is [JsonExtensionData]. Read more
Extension data is now written when an object is serialized. Reading and writing extension data makes it possible to automatically round-trip all JSON without adding every property to the .NET type you’re deserializing to. Only declare the properties you’re interested in and let extension data do the rest.
In your case key/value pair with 0,1,2,3.......N have dynamic data so your class will be
So create one property that collects all of your dynamic key/value pair with the attribute [JsonExtensionData]. And below I create that one with name DynamicData.
class MainObj
{
[JsonExtensionData]
public Dictionary<string, JToken> DynamicData { get; set; }
public int result_code { get; set; }
public string result_message { get; set; }
public string result_output { get; set; }
}
And then you can deserialize your JSON like
string json = "Your json here"
MainObj mainObj = JsonConvert.DeserializeObject<MainObj>(json);
Edit:
If you want to collect your dynamic key's value to class then you can use below the class structure.
class MainObj
{
[JsonExtensionData]
public Dictionary<string, JToken> DynamicData { get; set; }
[JsonIgnore]
public Dictionary<string, ChildObj> ParsedData
{
get
{
return DynamicData.ToDictionary(x => x.Key, y => y.Value.ToObject<ChildObj>());
}
}
public int result_code { get; set; }
public string result_message { get; set; }
public string result_output { get; set; }
}
public class ChildObj
{
public string id { get; set; }
public string name { get; set; }
public string cdate { get; set; }
public string _private { get; set; }
public string userid { get; set; }
public int subscriber_count { get; set; }
}
And then you can deserialize your JSON like
MainObj mainObj = JsonConvert.DeserializeObject<MainObj>(json);
And then you can access each of your deserialized data like
int result_code = mainObj.result_code;
string result_message = mainObj.result_message;
string result_output = mainObj.result_output;
foreach (var item in mainObj.ParsedData)
{
string key = item.Key;
ChildObj childObj = item.Value;
string id = childObj.id;
string name = childObj.name;
string cdate = childObj.cdate;
string _private = childObj._private;
string userid = childObj.userid;
int subscriber_count = childObj.subscriber_count;
}
I'd recommend JObject from the Newtonsoft.Json library
e.g. using C# interactive
// Assuming you've installed v10.0.1 of Newtonsoft.Json using a recent version of nuget
#r "c:\Users\MyAccount\.nuget\.nuget\packages\Newtonsoft.Json\10.0.1\lib\net45\Newtonsoft.Json.dll"
using Newtonsoft.Json.Linq;
var jobj = JObject.Parse(File.ReadAllText(#"c:\code\sample.json"));
foreach (var item in jobj)
{
if (int.TryParse(item.Key, out int value))
{
Console.WriteLine((string)item.Value["id"]);
// You could then convert the object to a strongly typed version
var listItem = item.Value.ToObject<YourObject>();
}
}
Which outputs:
4
5
6
See this page for more detail
https://www.newtonsoft.com/json/help/html/QueryingLINQtoJSON.htm
Here is the Json data that I got
{
"Data": {
"namelist": [
{
"name": "Elson Mon",
"Information": {
"Age": 45.0,
"Height": 168.7,
"Weight": 75.4,
"Birthdate": "1992-03-03"
},
"Married Status": "Single"
}
]
}
}
And here are my models
public class Information
{
public double Age { get; set; }
public double Height { get; set; }
public double Weight { get; set; }
public string Birthdate { get; set; }
}
public class Namelist
{
public string name { get; set; }
public Information Information { get; set; }
public string MarriedStatus { get; set; }
}
public class Data
{
public List<Namelist> namelist { get; set; }
}
public class RootObject
{
public Data Data { get; set; }
}
How can I deserialize the Json format string and assign into variable ?
I'm trying to use
dynamic jsonResponse = JsonConvert.DeserializeObject<RootObject>(json);
to deserialize the Json data but have totally no idea on how to assign it into different variable.
Am I right in assuming your problem is actually assigning the result to a variable?
If that's the case, you needn't bother figuring out the type (although it's pretty obvious here - you're deserializing a string into RootObject, so if this works, you'll naturally have a RootObject). Just let the compiler do it for you:
var jsonResponse = JsonConvert.DeserializeObject<RootObject>(json);
You can then hover over "var" to see the type. It's much more convenient when you really have no idea what you're working with or if the type is something rather ugly like IEnumerable<KeyValuePair<int, List<string>>>.
Avoid the dynamic type in such cases; always prefer putting the actual type or "var". The compiler doesn't know what you've got if you store it in a dynamic, so it won't issue any warnings if you're using your object in an inappropriate way, you'll face the consequences run-time.
You are in the right path.
RootObject obj = JsonConvert.DeserializeObject<RootObject>(json);
Example:
public static void Main(string[] args)
{
string json = #"{
'Data': {
'namelist': [
{
'name': 'Elson Mon',
'Information': {
'Age': 45.0,
'Height': 168.7,
'Weight': 75.4,
'Birthdate': '1992-03-03'
},
'Married Status': 'Single'
}
]
}
}";
RootObject obj = JsonConvert.DeserializeObject<RootObject>(json);
}
Current I have a project where I'm getting the following sample data ( I want to retrieve only the ids within this json string and stuff them into IEnumerables (explained below):
{
"states": [
{
"id": "AL",
"text": "Alabama (AL)"
},
{
"id": "CO",
"text": "Colorado (CO)"
}
],
"cities": [
{
"id": 71761,
"text": "New Brockton, AL"
},
{
"id": 74988,
"text": "Nathrop, CO"
}
],
"zipCodes": []
}
Notice in the zipCodes, I am getting an empty set, so there is no "id" or "text".
I want to be able to create several IEnumerables from the properties found in this JSON string.
I created an object called Locations that looks like this:
public class Location
{
public IEnumerable<string> States { get; set; }
public IEnumerable<string> ZipCodes { get; set; }
public IEnumerable<decimal> Cities { get; set; }
}
The best way I found to going about this approach is to do each data property one by one and convert, formValues is the json string:
JArray arrStates = (JArray)formValues["states"];
JArray arrCities = (JArray)formValues["cities"];
JArray arrZip = (JArray)formValues["zipCodes"];
and then set the properties in the location object as so:
Location loc = new Location();
loc.States = arrStates.Children().Select(m=>m["id"].Value<string>());
loc.ZipCodes = arrCities.Children().Select(m=>m["id"].Value<string>());
loc.Cities = arrZip.Children().Select(m=>m["id"].Value<string>());
I was wondering if there's a better way of doing this instead of doing all this code maintenance for whenever my json response adds a new property. In fact, I think there's going to be about ten more properties added to the json string.
I want it to be reduced down to where I could just update the Location object, and have the json automatically map to the properties that way. Or atleast a solution that has less maintenance than what I'm doing now.
Also I was wondering if JsonConvert.DeserializeObject would work in my case; but read that JSON.NET treats an IEnumerable as an array, so I'm stumped on this one.
JsonConvert.DeserializeObject would work in your case and it will have less maintenance than what you're doing now.
If you enter your json data to http://json2csharp.com, below is the generated class definition that you can use, I renamed RootObject to Location
public class State
{
public string id { get; set; }
public string text { get; set; }
}
public class City
{
public int id { get; set; }
public string text { get; set; }
}
public class Location
{
public List<State> states { get; set; }
public List<City> cities { get; set; }
public List<object> zipCodes { get; set; }
}
This is how you deserialize the json data into Location
string jsonData = ...; // set the json data here
var location = JsonConvert.DeserializeObject<Location>(jsonData);
You can enumerate through the nested properties to get the ids, for example location.states[0].id will return "AL" and location.cities[1].id will return 74988.
If there's a new property in the json data, let's say it's named countries with id and text like in states, you can create a new Country class
public class Country
{
public string id { get; set; }
public string text { get; set; }
}
and add countries property to Location class
public class Location
{
public List<State> states { get; set; }
public List<City> cities { get; set; }
public List<object> zipCodes { get; set; }
public List<Country> countries { get; set; }
}
i have the following json string (jsonString)
[
{
"name":"Fruits",
"references":[
{"stream":{"type":"reference","size":"original",id":"1"}},
],
"arts":[
{"stream":{"type":"art","size":"original","id":"4"}},
{"stream":{"type":"art","size":"medium","id":"9"}},
]
}
]
and the following C# objects
class Item
{
public string Name { get; set; }
public List<Stream> References { get; set; }
public List<Stream> Arts { get; set; }
public Item()
{
}
}
class Stream
{
public string Type { get; set; }
public string Size { get; set; }
public string Id { get; set; }
public Stream()
{
}
}
and the following code
Item item = JsonConvert.DeserializeObject<Item>(jsonString);
when I run the code, it creteas the correct number of references and arts, but each stream has null value (type = null, size = null).
is it posible to do this json.net deserializeobject method or should I manually deserialize ?
EDIT: Okay, ignore the previous answer. The problem is that your arrays (references and arts) contain objects which in turn contain the relevant data. Basically you've got one layer of wrapping too many. For example, this JSON works fine:
[
{
"name":"Fruits",
"references":[
{"Type":"reference","Size":"original","Id":"1"},
],
"arts":[
{"Type":"art","Size":"original","id":"4"},
{"type":"art","size":"medium","id":"9"},
]
}
]
If you can't change the JSON, you may need to introduce a new wrapper type into your object model:
public class StreamWrapper
{
public Stream Stream { get; set; }
}
Then make your Item class have List<StreamWrapper> variables instead of List<Stream>. Does that help?