Convert JObject to custome entity - c# - c#

I have the following JSON that is returned from an API call:
{
"Success": true,
"Message": null,
"Nodes": [
{
"Title": "Title 1",
"Link": "http://www.google.com",
"Description": null,
"PubDate": "2014-06-19T13:32:00-07:00"
},
{
"Title": "Title 2",
"Link": "http://www.bing.com",
"Description": null,
"PubDate": "2014-06-26T13:14:00-07:00"
},
]
}
I have the following object to convert the JSON to an custom object
[JsonObject(MemberSerialization.OptIn)]
public class MyApiResponse
{
[JsonProperty(PropertyName = "Success")]
public bool Success { get; set; }
[JsonProperty(PropertyName = "Message")]
public string Message { get; set; }
[JsonProperty(PropertyName = "Nodes")]
public IEnumerable<object> Nodes { get; set; }
}
I am able to execute the following line of code to deserialize to the MyApiResponse object.
MyApiResponse response = JsonConvert.DeserializeObject<MyApiResponse>(json);
I would like to loop through the Nodes property of the MyApiResponse object can serialize them into another object. When I try the following snippet of code it throws an error:
foreach(var item in response.Nodes)
{
MyObject obj = JsonConvert.DeserializeObject<MyObject>(item.ToString());
}
What do I need to do to convert item into my MyObject in the foreach loop?

You just need to define a class to represent a Node, then change the Nodes property in your MyApiResponse class to be a List<Node> (or IEnumerable<Node> if you prefer) instead of an IEnumerable<object>. When you call JsonConvert.DeserializeObject<MyApiResponse>(json), the whole JSON response is deserialized in one go. There should not be a need to deserialize each child item individually.
[JsonObject(MemberSerialization.OptIn)]
public class Node
{
[JsonProperty(PropertyName = "Title")]
public string Title { get; set; }
[JsonProperty(PropertyName = "Link")]
public string Link { get; set; }
[JsonProperty(PropertyName = "Description")]
public string Description { get; set; }
[JsonProperty(PropertyName = "PubDate")]
public DateTime PubDate { get; set; }
}
[JsonObject(MemberSerialization.OptIn)]
public class MyApiResponse
{
[JsonProperty(PropertyName = "Success")]
public bool Success { get; set; }
[JsonProperty(PropertyName = "Message")]
public string Message { get; set; }
[JsonProperty(PropertyName = "Nodes")]
public List<Node> Nodes { get; set; }
}
Then:
MyApiResponse response = JsonConvert.DeserializeObject<MyApiResponse>(json);
foreach (Node node in response.Nodes)
{
Console.WriteLine(node.Title);
}

Related

Convert JSON array to a c# object collection

I've a JSON like below,
[
{
"document":
{
"createdDate":1476996267864,
"processedDate":1476996267864,
"taxYear":"2015",
"type":"user_document"
}
},
{
"document":
{
"createdDate":1476998303463,
"processedDate":0,
"taxYear":"2015",
"type":"user_document"
}
}
]
I need to convert it into a c# object. My object type is as below-
public class UserDocument
{
[JsonProperty(PropertyName = "type")]
public string type { get; set; }
[JsonProperty(PropertyName = "taxYear")]
public string taxYear { get; set; }
[JsonProperty(PropertyName = "createdDate")]
public string createdDate { get; set; }
[JsonProperty(PropertyName = "processedDate")]
public string processedDate { get; set; }
}
I'm using below code to deserialize the json but all UserDocument properties are null
var test = JsonConvert.DeserializeObject<List<UserDocument>>(jsonString);
Why am I getting all UserDocument properties are null, what's wrong here? I'm not getting any error.
Also can you suggest a good example in getting CouchBase queryresult into a .net object.
Seems your json is not in correct format. If I say your json is like
[
"document":
{
"createdDate":1476996267864,
"processedDate":1476996267864,
"taxYear":"2015",
"type":"user_document"
},
"document":
{
"createdDate":1476998303463,
"processedDate":0,
"taxYear":"2015",
"type":"user_document"
}
]
Then create a model like
public class Document
{
public UserDocument document {get;set;}
}
and change your UserDocument model's createdDate and processedDate properties as double because its like that in your json
public class UserDocument
{
[JsonProperty(PropertyName = "type")]
public string type { get; set; }
[JsonProperty(PropertyName = "taxYear")]
public string taxYear { get; set; }
[JsonProperty(PropertyName = "createdDate")]
public double createdDate { get; set; }
[JsonProperty(PropertyName = "processedDate")]
public double processedDate { get; set; }
}
and then deserialize
var test = JsonConvert.DeserializeObject<List<Document>>(jsonString);
Something like this (using Newtonsoft.Json.Linq):
var documents = JArray.Parse(json).Select(t => t["document"].ToObject<UserDocument>());

Invalid class property declaration for json mapping

I have below json received from mailgun API.
{
"items": [{
"delivery-status": {
"message": null,
"code": 605,
"description": "Not delivering to previously bounced address",
"session-seconds": 0
},
"event": "failed",
"log-level": "error",
"recipient": "test#test.com"
},
{
//some other properties of above types
}]
}
Now I was trying to create a class structure for above json to auto-map the properties after deserializing.
public class test
{
public List<Item> items { get; set; }
}
public class Item
{
public string recipient { get; set; }
public string #event { get; set; }
public DeliveryStatus delivery_status { get; set; }
}
public class DeliveryStatus
{
public string description { get; set; }
}
This is how I deserialize and try to map the properties.
var resp = client.Execute(request);
var json = new JavaScriptSerializer();
var content = json.Deserialize<Dictionary<string, object>>(resp.Content);
test testContent = (test)json.Deserialize(resp.Content, typeof(test));
var eventType = testContent.items[0].#event;
var desc = testContent.items[0].delivery_status.description; //stays null
Now in the above class Item, recipient and #event gets mapped properly and since it was a keyword I was suppose to use preceding # character and it works well. But the delivery-status property from json, does not get mapped with delevery_status property in class DeliveryStatus. I have tried creating it as deliveryStatus or #deliver-status. The earlier on doesn't map again and the later one throws compile time exception. Is there anyway these things can be handled, like declaring a property with - in between? I cannot change response json as it is not getting generated from my end. Hoping for some help.
Update
Changed the class as below referring this answer, but did not help. Its null again.
public class Item
{
public string #event { get; set; }
[JsonProperty(PropertyName = "delivery-status")]
public DeliveryStatus deliveryStatus { get; set; }
}
I am not sure what the issue is at your end, but at least it works if you use this code. Make sure to include a recent version of Newtonsoft.Json in your project and you should be fine.
public class DeliveryStatus
{
public object message { get; set; }
public int code { get; set; }
public string description { get; set; }
[JsonProperty("session-seconds")]
public int session_seconds { get; set; }
}
public class Item
{
[JsonProperty("delivery-status")]
public DeliveryStatus delivery_status { get; set; }
public string #event { get; set; }
[JsonProperty("log-level")]
public string log_level { get; set; }
public string recipient { get; set; }
}
public class RootObject
{
public List<Item> items { get; set; }
}
public static void Main(string[] args)
{
string json = #"{
""items"": [{
""delivery-status"": {
""message"": null,
""code"": 605,
""description"": ""Not delivering to previously bounced address"",
""session-seconds"": 0
},
""event"": ""failed"",
""log-level"": ""error"",
""recipient"": ""test#test.com""
}]
}";
RootObject r = JsonConvert.DeserializeObject<RootObject>(json);
}

Deserialize JSON one item at a time without Json.NET

what is best way to deseriaze JSON-file one item at a time?
I have large JSON-file and I cannot read it to string, because I get error:
"An unhandled exception of type 'System.OutOfMemoryException' occurred in mscorlib.dll"
How I can deserialize this JSON-file one item at a time, without using Json.NET ?
I found this, but it uses Json.NET:
Deserialize json array stream one item at a time
(I think that I have to use StreamReader when I read file, but how I can deserialize it?)
I have created DataContract:
[DataContract]
public class Header
{
[DataMember(Name = "time")]
public string time { get; set; }
[DataMember(Name = "code")]
public string code { get; set; }
[DataMember(Name = "type")]
public string type { get; set; }
[DataMember(Name = "value")]
public string value { get; set; }
}
[DataContract]
public class Body : IDeserializationCallback
{
[DataMember(Name = "file")]
public string file { get; set; }
[DataMember(Name = "title")]
public string title { get; set; }
[DataMember(Name = "rows")]
public List<string> rows { get; set; }
public Dictionary<int, string> RowHeaders { get; protected set; }
public void OnDeserialization(object sender)
{
RowHeaders = new Dictionary<int, string>();
String[] headers = this.title.Split(';');
for (int i = 0; i < headers.Length; i++)
{
RowHeaders.Add(i);
}
}
}
[DataContract]
public class Dwresult
{
[DataMember(Name = "header")]
public Header header { get; set; }
[DataMember(Name = "body")]
public List<Body> body { get; set; }
}
[DataContract]
public class RootObject
{
[DataMember(Name = "dwresult")]
public Dwresult dwresult { get; set; }
}
Here is example JSON:
{
"dwresult": {
"header": {
"time": "2015.08.02 10:14:51",
"code": "OK",
"type": "TEST",
"count": "2"
},
"body": [{
"file": "test_file_one",
"title": "EXAMPLE1;EXAMPLE2;EXAMPLE3;EXAMPLE4;EXAMPLE5;EXAMPLE6;EXAMPLE7;EXAMPLE8;EXAMPLE9;EXAMPLE10;EXAMPLE11;EXAMPLE12;EXAMPLE13;EXAMPLE14;EXAMPLE15;EXAMPLE16;EXAMPLE17;EXAMPLE18;EXAMPLE19;EXAMPLE20;",
"rows": [
"1;NAME1;CODE1;;;123;DATA1;1;1;1.2;;TOWN;3;1990;1991;2000;;;ACCOUNT;DOWNLOADED;",
"2;NAME2;CODE2;;;456;DATA2;2;2;2.3;;TOWN2;4;1991;1992;2001;;;ACCOUNT;DOWNLOADED;",
"3;NAME3;CODE3;;;789;DATA3;3;3;3.4;;TOWN3;5;1992;1993;;PERSON;AGE;AC;DOWNLOADED;",
]
},{
"file": "test_file_two",
"title": "ANOT_EXAMPLE1;ANOT_EXAMPLE2;ANOT_EXAMPLE3;ANOT_EXAMPLE4;ANOT_EXAMPLE5;ANOT_EXAMPLE6;ANOT_EXAMPLE7;ANOT_EXAMPLE8;ANOT_EXAMPLE9;ANOT_EXAMPLE10;ANOT_EXAMPLE11;ANOT_EXAMPLE12;ANOT_EXAMPLE13;ANOT_EXAMPLE14;ANOT_EXAMPLE15;ANOT_EXAMPLE16;ANOT_EXAMPLE17;ANOT_EXAMPLE18;ANOT_EXAMPLE19;ANOT_EXAMPLE20;ANOT_EXAMPLE21;ANOT_EXAMPLE22;ANOT_EXAMPLE23;ANOT_EXAMPLE24;ANOT_EXAMPLE25;ANOT_EXAMPLE26;ANOT_EXAMPLE27;ANOT_EXAMPLE28;ANOT_EXAMPLE29;ANOT_EXAMPLE30;ANOT_EXAMPLE31;ANOT_EXAMPLE32;ANOT_EXAMPLE33;ANOT_EXAMPLE34;",
"rows": [
"4;NAME4;SCHOOL;;;01;DATA1;1;TOWN;04;;2011;2012;;;1;;;;PERSON;NUMBER;;;;;;;;;56;ACCOUNT;;;DOWNLOADED;",
"5;NAME5;SCHOOL;;;02;DATA2;2;TOWN2;05;;2012;2013;;;2;;;;PERSON;NUMBER;;;;;;;;;57;ACCOUNT;;;DOWNLOADED;",
"6;NAME6;SCHOOL;;;03;DATA3;3;TOWN3;06;;2013;2014;;;3;;31;;PERSON;NUMBER;;;;;;;;;58;ACCOUNT;;;DOWNLOADED;",
]
}
]
}
}

Parse JSON to object

I am working with box api, and trying to parse json object to a class.
This is the json:
{
"type":"folder",
"id":"0",
"sequence_id":null,
"etag":null,
"name":"All Files",
"created_at":null,
"modified_at":null,
"description":"",
"size":9049537,
"path_collection":
{
"total_count":0,"entries":[]
},
"created_by":
{
"type":"user","id":"","name":"","login":""
},
"modified_by":
{
"type":"user",
"id":"111",
"name":"a a",
"login":"a#gmail.com"
},
"trashed_at":null,
"purged_at":null,
"content_created_at":null,
"content_modified_at":null,
"owned_by":
{
"type":"user",
"id":"111",
"name":"a a",
"login":"a#gmail.com"
},
"shared_link":null,
"folder_upload_email":null,
"parent":null,
"item_status":"active",
"item_collection":
{
"total_count":4,
"entries":
[
{
"type":"file",
"id":"22887167395",
"sequence_id":"0",
"etag":"0",
"sha1":"883c99863eefc0f46b3d34915cc4d97a6008fabf",
"name":"13.ppt"
},
{
"type":"file",
"id":"22887169687",
"sequence_id":"0",
"etag":"0",
"sha1":"a345fd68b1c90a3678a3e746e0e5343693d8a022",
"name":"6.docx"
}
],
"offset":0,
"limit":100,
"order":
[
{
"by":"type",
"direction":"ASC"
},
{
"by":"name",
"direction":"ASC"
}
]
}
}
Basically, this is the root folder (in that case) that contains two files:
13.ppt
6.docx
I created a class:
[JsonObject(MemberSerialization.OptIn)]
public class BoxFile
{
[JsonProperty(PropertyName = "type")]
public string Type { get; internal set; }
[JsonProperty(PropertyName = "id")]
public string Id { get; internal set; }
[JsonProperty(PropertyName = "sequence_id")]
public string SequenceId { get; internal set; }
[JsonProperty(PropertyName = "etag")]
public string Etag { get; internal set; }
[JsonProperty(PropertyName = "name")]
public string Name { get; internal set; }
[JsonProperty(PropertyName = "created_at")]
public string CreatedAt { get; internal set; }
[JsonProperty(PropertyName = "modified_at")]
public string ModifiedAt { get; internal set; }
[JsonProperty(PropertyName = "description")]
public string Description { get; internal set; }
[JsonProperty(PropertyName = "size")]
public long Size { get; internal set; }
[JsonProperty(PropertyName = "item_collection")]
public IEnumerable<BoxFile> ItemCollection { get; internal set; }
}
But the "item_collection" part is not working.. it gives me an error..
How do I get a list of subfiles inside "item_collection"?
I use it by:
private T ParseJson<T>(string json) where T : class, new()
{
JObject jobject = JObject.Parse(json);
return JsonConvert.DeserializeObject<T>(jobject.ToString());
}
And:
BoxFile parsed = ParseJson<BoxFile>(json);
You are getting an error because your class structure does not match your JSON. Specifically, in the JSON, the item_collection property is an object, not a list. That JSON object has two properties, total_count and entries, the latter of which contains the actual list of files. To handle this, you need to define another class:
public class ItemCollection
{
[JsonProperty(PropertyName = "entries")]
public IEnumerable<BoxFile> Entries { get; internal set; }
}
and then change the ItemCollection property in your BoxFile class to use this new class:
[JsonProperty(PropertyName = "item_collection")]
public ItemCollection ItemCollection { get; internal set; }
You can then access the list of files like this:
BoxFile parsed = ParseJson<BoxFile>(json);
foreach (BoxFile file in parsed.ItemCollection.Entries)
{
Console.WriteLine(file.Name);
}
Here is a working demo: https://dotnetfiddle.net/DB9Coc
As an aside, you can simplify your ParseJson method to one line. There is no need to parse the JSON to an JObject, turn it back into JSON and then parse it again.
private T ParseJson<T>(string json) where T : class, new()
{
return JsonConvert.DeserializeObject<T>(json);
}

How can you deserialize JSON data in C# (using DataContractJsonSerializer) without knowing all property names?

I have been using the DataContractJsonSerializer to convert data returned from the HubSpot API into strongly-typed objects, but I'm having some trouble with the user profile object.
In this example, I am able to get the Id and IsContact properties, but can't figure out how to get the list of properties since I don't know in advance what those can be. I would like to make Properties a Dictionary but I'm not sure how to do this. I don't care about the versions for each property, just the value.
This is a simplified example of the data that is returned by the API:
{
"vid": 72361,
"is-contact": true,
"properties": {
"city": {
"value": "Burlington",
"versions": [
{
"value": "Burlington",
"source-type": "SALESFORCE",
"source-id": "continuous",
"source-label": null,
"timestamp": 1384319976006,
"selected": false
}
]
},
"country": {
"value": "US",
"versions": [
{
"value": "US",
"source-type": "SALESFORCE",
"source-id": "continuous",
"source-label": null,
"timestamp": 1384319976006,
"selected": false
}
]
},
"company": {
"value": "Bridgeline Digital",
"versions": [
{
"value": "Bridgeline Digital",
"source-type": "SALESFORCE",
"source-id": "continuous",
"source-label": null,
"timestamp": 1384319976006,
"selected": false
}
]
}
}
}
This is the object I am trying to deserialize to:
[DataContract]
public class HubSpotUserProfile
{
[DataMember(Name = "vid")]
public int Id { get; set; }
[DataMember(Name = "is-contact")]
public bool IsContact { get; set; }
[DataMember(Name = "redirect")]
public string RedirectUrl { get; set; }
[DataMember(Name = "properties")]
public Dictionary<string, HubSpotUserProfileProperty> Properties { get; set; }
}
[DataContract]
public class HubSpotUserProfileProperty
{
[DataMember(Name = "value")]
public string Value { get; set; }
}
I call this method to perform the deserialization:
public static T Post<T>(string url, string postData) where T : class
{
string json = Post(url, postData);
if (!String.IsNullOrWhiteSpace(json))
{
using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(json)))
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
return (T)serializer.ReadObject(stream);
}
}
return null;
}
When I do this, no error is thrown, but Properties always has a Count of 0. Any idea on how I can accomplish this goal?
Use JsonObject type for your Properties property. In some very strange case DataContractJsonSerializer doesn't support Dictionary<> type in this case
If JSON.NET is an option then James has recently added ExtensionData support. See http://james.newtonking.com/archive/2013/05/08/json-net-5-0-release-5-defaultsettings-and-extension-data.
public class DirectoryAccount
{
// normal deserialization
public string DisplayName { get; set; }
// these properties are set in OnDeserialized
public string UserName { get; set; }
public string Domain { get; set; }
[JsonExtensionData]
private IDictionary<string, JToken> _additionalData;
[OnDeserialized]
private void OnDeserialized(StreamingContext context)
{
// SAMAccountName is not deserialized to any property
// and so it is added to the extension data dictionary
string samAccountName = (string)_additionalData["SAMAccountName"];
Domain = samAccountName.Split('\\')[0];
UserName = samAccountName.Split('\\')[1];
}
}
Depending on your chosen package for deserializing objects, your current models will work. We use JSon.Net for this exact purpose with HubSpot.
Here's samples of what we use...
[DataContract]
public class ContactHubSpotModel {
// snip for brevity
[DataMember(Name = "properties")]
public Dictionary<string, ContactProperty> Properties { get; set; }
}
[DataContract]
public class ContactProperty
{
[DataMember(Name = "value")]
public string Value { get; set; }
[DataMember(Name = "versions")]
List<ContactPropertyVersion> Versions { get; set; }
}
[DataContract]
public class ContactPropertyVersion
{
[DataMember(Name = "value")]
public string Value { get; set; }
[DataMember(Name = "source-type")]
public string SourceType { get; set; }
[DataMember(Name = "source-id")]
public string SourceId { get; set; }
[DataMember(Name = "source-label")]
public string SourceLabel { get; set; }
[DataMember(Name = "timestamp")]
public long Timestamp { get; set; }
[DataMember(Name = "selected")]
public bool Selected { get; set; }
}
Then you can dump a copy of your contact output into a file for validation like so...
string contactJson = GetContactString(); // pulls sample data stored in a .txt
ContactHubSpotModel contactModel = JsonConvert.DeserializeObject<ContactHubSpotModel>(contactJson);

Categories

Resources