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;",
]
}
]
}
}
Related
I am starting c# and I was asked to create a small Api using a given Json file as DB.
My json file looks like:
{"Items": [
{
"id": 1,
"name": "Apple",
"price": 12.50,
"image": "some url",
"description": "Some text",
"tags": [ "fruit", "red" ],
"category": "fruit"
},
]}
I created a model:
public class Product
{
public int ID { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public string Image { get; set; }
public string Description { get; set; }
public List<Tags> Tags { get; set; }
public string Category { get; set; }
}
public class Tags
{
public string Tag { get; set; }
}
And my controller looks like:
[ApiController]
[Route("api/[controller]")]
public class ProductController : Controller
{
[HttpGet]
public IEnumerable<Product> Get()
{
StreamReader r = new StreamReader("./items.json");
string jsonString = r.ReadToEnd();
List<Product> productsList = JsonConvert.DeserializeObject<List<Product>>(jsonString);
return productsList;
}
}
The error I get:
Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[Kata.Product]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
As I am new to c#, I am having trouble to find out how to simply return what I have in my Json file. At some point I was able to return the list by changing the json file(not the greatest idea) but all the items were null.
Thank you
You have a bug in your json classes. You can't use a special class for the tags, try to replace it by string array or list. The same about items. You deserialized the whole Root object, items just a property of this object. So since you don't need the whole object but just list of items, you have to select only them.
var jsonDeserialized= JsonConvert.DeserializeObject<Root> (jsonString);
List<Product> productsList = jsonDeserialized.Items ;
classes
public class Product
{
public int id { get; set; }
public string name { get; set; }
public double price { get; set; }
public string image { get; set; }
public string description { get; set; }
public List<string> tags { get; set; }
public string category { get; set; }
}
public class Root
{
public List<Product> Items { get; set; }
}
and fix json
{
"Items": [{
"id": 1,
"name": "Apple",
"price": 12.50,
"image": "some url",
"description": "Some text",
"tags": ["fruit", "red"],
"category": "fruit"
}]
}
I have the simple JSON:
[
{
"new_as_cod": "0010955",
"as_nome": "NAME",
"as_cpf": "1212121212",
"as_email": "IM#UOL.COM.BR",
"as_cep": "88.025-200",
"igr_nome": "1\u00aa IGREJA BATISTA - FLORIANOPOLIS",
"id": "2781",
"valor": "50.00",
"pg_tipo_id": "CC",
"status": "Ativo",
"idstatus": "1"
}
]
... and a C# class generated from here:
public class RootObject
{
public string new_as_cod { get; set; }
public string as_nome { get; set; }
public string as_cpf { get; set; }
public string as_email { get; set; }
public string as_cep { get; set; }
public string igr_nome { get; set; }
public string id { get; set; }
public string valor { get; set; }
public string pg_tipo_id { get; set; }
public string status { get; set; }
public string idstatus { get; set; }
}
I have tried this:
RootObject data = JsonConvert.DeserializeObject<RootObject>(stringdate);
But I get the error:
How can I solve it?
[{ "new_as_cod": "0010955", "as_nome": "NAME", "as_cpf": "1212121212", "as_email": "IM#UOL.COM.BR", "as_cep": "88.025-200", "igr_nome": "1\u00aa IGREJA BATISTA - FLORIANOPOLIS", "id": "2781", "valor": "50.00", "pg_tipo_id": "CC", "status": "Ativo", "idstatus": "1" }]
If it has [] this is a collection.
Try this.
JsonConvert.DeserializeObject<List<RootObject>>(stringdate);
Yes, this JSON is a collection, so the variable needs to be list too.
List<RootObject> data = JsonConvert.DeserializeObject<List<RootObject>>(stringdate);
I am getting the json from zoho. I have a JSON like the following:
{
"response": {
"result": {
"Leads": {
"row": [
{
"no": "1",
"FL": [
{
"content": "1325469000000679001",
"val": "LEADID"
},
{
"content": "1325469000000075001",
"val": "SMOWNERID"
},
{
"content": "Geoff",
"val": "Lead Owner"
},
]
},
{
"no": "2",
"FL": [
{
"content": "1325469000000659017",
"val": "LEADID"
},
{
"content": "1325469000000075001",
"val": "SMOWNERID"
},
{
"content": "Geoff",
"val": "Lead Owner"
},
]
},
]
}
},
"uri": "/crm/private/json/Leads/getRecords"
}
}
I am using the following classes:
public class Row
{
[JsonProperty(PropertyName = "row")]
public List<Leads> row { get; set; }
}
public class Leads
{
[JsonProperty(PropertyName = "no")]
public string nbr { get; set; }
[JsonProperty(PropertyName = "FL")]
public List<Lead> FieldValues { get; set; }
}
public class Lead
{
[JsonProperty(PropertyName = "content")]
public string Content { get; set; }
[JsonProperty(PropertyName = "val")]
public string Val { get; set; }
}
I try to deserialize the json and get back nothing:
var mList = JsonConvert.DeserializeObject<IDictionary<string, Row>>(result);
This is the first time working with Json so any help would be appreciated!
Usually when that happens it is because your class model for deserialization is wrong. Rather than trying to hand-craft the classes I like to use http://json2csharp.com. Just plug in your JSON and it gives you the necessary C# classes. In your case it provides the following.
public class FL
{
public string content { get; set; }
public string val { get; set; }
}
public class Row
{
public string no { get; set; }
public List<FL> FL { get; set; }
}
public class Leads
{
public List<Row> row { get; set; }
}
public class Result
{
public Leads Leads { get; set; }
}
public class Response
{
public Result result { get; set; }
public string uri { get; set; }
}
public class RootObject
{
public Response response { get; set; }
}
You can then deserialize into RootObject using:
var mList = JsonConvert.DeserializeObject<RootObject>(result);
Feel free to rename RootObject to whatever name you like better.
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);
}
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);