Hi I am having trouble deserializing my JSON object and displaying in a DataSet.
I have had partial success in that I am displaying most of the data except for the data that is contained in nested arrays.
What I have done is deserialize the data into a generic list and then from that list have converted it into a dataset which I will insert into a database. I am using JSON.net, more specifically the JsonConvert class to deserialize the string and then using a helper class to convert it to a dataset, which I stole from here and modified From Here. Now this works well until I hit the nested arrays.
On the first array I can see the data being returned in the XML but it does not appear in the returned dataset and the other array simply does not feature in the request at all.
I am handling the first array as below:
public List<string> Categories { get; set; }
This is what was as per json2csharp and it partially works in that I can see the categories options change depending on how many I select. For instance if i select 4 it will return 4 but the rows will be empty.
After I click on Categories it displays these 4 rows.
Any ideas on how i can get around this?
My second array is not being requested or returned at all. I have created a seperate class to handle the elements as below:
public class EventDate
{
public DateTime EndDate { get; set; }
public DateTime StartDate { get; set; }
}
and call it using this:
public List EventDates { get; set; }
This produces the error Column requires a valid Data Type
I have seen some examples that say you have to deserialize these using custom converters and others that say you should be able to do as I have done above. The format for the above are as per the json2charp website.
I have tried accessing the Categories as a string array but the same issue arose where I could see the returned data in the XML but not in the dataset.
Below I have included the deserializejson class that uses the Jsonconvert class to deserialize the jsonstring.
public List<RootObject> DeSerializeJsonString(string jsonString)
{
List<RootObject> list = new List<RootObject>();
list = (List<RootObject>)JsonConvert.DeserializeObject<List<RootObject>>(jsonString);
return list;
}
Any help would be greatly appreciated, cheers.
Related
I am deserializing a json file into C# objects, in this case MTG cards (json from scryfall.com). Previously I solved the problem with MSSQL; I imported the json data into the database with OPENJSON mapping each element I needed to a column with a proper name, and then created a new json file with properties that matched the class I needed in the application.
For properties like arena_id that have only one value, or for arrays that were used as strings (color_identity), it was not an issue, but for arrays such as card_faces (cards that have 2 playable sides) I had to specify which element of the array I wanted to import.
arena_id int '$.arena_id',
...
[color_identity] nvarchar(max) AS JSON,
...
name_front varchar(100) '$.card_faces[0].name',
mana_cost_front varchar(30) '$.card_faces[0].mana_cost',
name_back varchar(100) '$.card_faces[1].name',
mana_cost_back varchar(30) '$.card_faces[1].mana_cost',
From the SQL tailored file I deserialized every object accordingly, but now I'm trying to do it without SQL and with more direct influence as to what goes where.
As mentioned before, for properties that do not need to be deconstructed I know I can just pick the same property name in the class and it gets accepted easily. My problem is with array properties that I should divide into separate properties with different names.
Is it possible in C# to deserialize in a similar way?
I'm thankful for all kinds of hints and tips as I am relatively new to programming with only one year in a training course.
You just need to create a class that properly represents the expected JSON format, EG:
public class MyClass
{
public int Arena_Id { get; set; }
public CardFace[] Card_Faces { get; set; }
}
public class CardFace
{
public string Name { get; set; }
public string Mana_Cost { get; set; }
}
Then deserialize your JSON:
string json = ... // your data
MyClass x = new Newtonsoft.Json.JsonSerializer() // or whichever serializer you want
.DeSerialize<MyClass>(json)
With this deserialized instance of your class, you can then translate it to another class matching the structure you require.
I am guessing that you are simply able to at least call the JSON.
C# does have a good JSON deserialization directive.
// keep the class as close to how it will show up on the JSON
public class MTGCard
{
public string name;
public int manaCost;
...
}
// then you should be able to just
currentCard = JsonSerializer.Deserialize<MTGCard>(jsonString);
The class and the json are close enough you should be able to simply use the Array features pull the cards you need and then just deserialize it on the call based
I am creating a windows phone silver light 8 app.
I have a Json string and I am trying to convert it into a List of objects and each object is a object of a class classed "Product" and list is supposed to be products. ultimately I want it to convert into Observable collection so that I can bind that collection to my listbox in my windows Silverlight phone app.
Here is my class
public class Product
{
public string _id { get; set; }
public string code { get; set; }
public string name { get; set; }
public string imgAddress { get; set; }
public int queryCount { get; set; }
}
Here is code to deserialize the json
var PDS = "{\"products\":[{\"_id\":\"58b2\",\"code\":\"59034\",\"name\":\"somename1\",\"imgAddress\":\"https://someimageurl/.../.jpg\",\"queryCount\":0},{\"_id\":\"58b3\",\"code\":\"59035\",\"name\":\"somename2\",\"imgAddress\":\"https://someimageurl2/.../.jpg\",\"queryCount\":1}]}";
var pds = JsonConvert.DeserializeObject<List<Product>>(PDS);
//PDS is actually very long string and the array products has a lot of objects but I am only writing 2 products here for simplicity.
Here is my collection for binding
public ObservableCollection<Product> Products { get; set; }
ERRORS
>> First I was getting parsing error so I escaped all quotes within the string like this \"
**>>**But then it was only converting to a normal string like object but I want to convert to a collection of products of type "Product"
>> Exception
Additional information: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[PivotApp1.Product]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path 'products', line 1, position 12.
Thanks in advance
You can deserialize it this way (but you'll have somehow to reformat your JSON string):
from
var PDS = "{"products":[{"_id":"58b2","code":"59034","name":"somename1","imgAddress":"https://someimageurl/.../.jpg","queryCount":0},{"_id":"58b3","code":"59035","name":"somename2","imgAddress":"https://someimageurl2/.../.jpg","queryCount":1}]}";
//PDS is actually very long string and the array products has a lot of objects but I am only writing 2 products here for simplicity.
to
var PDS = "[{'_id':'58b2','code':'59034','name':'somename1','imgAddress':'https://someimageurl/.../.jpg','queryCount':0},{'_id':'58b3','code':'59035','name':'somename2','imgAddress':'https://someimageurl2/.../.jpg','queryCount':1}]";
//PDS is actually very long string and the array products has a lot of objects but I am only writing 2 products here for simplicity.
Then
var pds = JsonConvert.DeserializeObject<List<Product>>(PDS);
More infos --> Deserialize a collection
No need of creating another class as suggested!
EDIT:
Actually you get this exception because your JSON string represents an object 'products' containing a list of 'Product' and this doesn't directly relate to your root class.
This is what your current JSON look like:
Your JSON string result should be something like that instead:
var PDS = "[{'_id':'58b2','code':'59034','name':'somename1','imgAddress':'https://someimageurl/.../.jpg','queryCount':0},{'_id':'58b3','code':'59035','name':'somename2','imgAddress':'https://someimageurl2/.../.jpg','queryCount':1}]";
Represented as following (notice the slight difference):
Using this JSON string, it will work with no exception raised:
var pds = JsonConvert.DeserializeObject<List<Product>>(PDS);
Or, if you can't change the resulting JSON string in PDS, you can do what J. Tuc suggested (via a new "RootClass").
your JSON string had to be changed to get the code to compile:
var PDS = "{'products':[{'_id':'58b2','code':'59034','name':'somename1','imgAddress':'https://someimageurl/.../.jpg','queryCount':0},{'_id':'58b3','code':'59035','name':'somename2','imgAddress':'https://someimageurl2/.../.jpg','queryCount':1}]}";
You need another object with a collection of Product as a property called products in order to deserialize your JSON
This may not be the best solution but it works:
Create another class:
public class RootObject
{
public List<Product> products;
}
use this code to deserialize your JSON:
var pds = JsonConvert.DeserializeObject(PDS, typeof(RootObject));
if you are in control of your JSON string you might consider changing it to this (removing 'products' property and ending up with just an array of products in the JSON string):
var PDS = "[{'_id':'58b2','code':'59034','name':'somename1','imgAddress':'https://someimageurl/.../.jpg','queryCount':0},{'_id':'58b3','code':'59035','name':'somename2','imgAddress':'https://someimageurl2/.../.jpg','queryCount':1}]";
Then you might be able to use the solution proposed by TaiT's (deserializing directly to a List of Product) :
var pds = JsonConvert.DeserializeObject<List<Product>>(PDS);
I am having difficulty writing the appropriate annotations to represent data which is returned from a JSON Get request which returns data like so:
[{"ProductCode":"0129923083091","Description":"DIESEL ","SalesLitres":6058.7347,"SalesValue":6416.2000},{"ProductCode":"0134039344902","Description":"UNLEADED ","SalesLitres":3489.8111,"SalesValue":3695.7100},
...
]
(ellipsis above just indicating that I could have variable number of these items returned)
In my model class (I am using MVVM approach for a Xamarin project but that's not over relevant here) I am using annotations to represent the model attributes
namespace App8.Models
{
public class ReportRow
{
[JsonProperty("ProductCode")]
public string ProductCode { get; set; } = string.Empty;
[JsonProperty("Description")]
public string Description { get; set; } = string.Empty;
[JsonProperty("SalesLitres")]
public double SalesLitres { get; set; } = 0.0;
[JsonProperty("SalesValue")]
public double SalesValue { get; set; } = 0.0;
}
}
I would like to annote another class which shows the container/contained relationship. However, I coming unstuck as there is no JSON attribute to provide in the annotation to represent the "root" of the returned collection.
I'd have no problem mapping the JSON to an object model for any JSON arrays which are named within the returned JSON. In that case I could create another class with a named JSON attribute which contained a C# List but I am trying to provide an appropriate model mapping for JSON which returns a list of items within an unnamed array.
Any ideas how I could approach this?
To deserialize that JSON, use:
JsonConvert.DeserializeObject<List<ReportRow>>(json)
(or any variant you wish, the key here is asking to deserialize a ICollection of ReportRow. It could be your own class implementing ICollection, or any of the builtins)
The same idea follows to JsonTextReader or whatever other means of deserializing JSON.NET offers. Just use a ICollection<YourType> as target type.
Very new to C# and JSON. I have been struggling with this problem for about a day and can't figure it out.
JSONLint states both JSON strings are valid.
Trying to deserialize the following
{"items":[{"id":"1122267","quantity":"1","bundle":"1"}],"seconds_ago":"1"}
throws the exception
An unhandled exception of type 'System.OutOfMemoryException' occurred
in Newtonsoft.Json.dll
If I try
{"items":[{"id":"1122267","quantity":"1","bundle":"1"}]}
it works.
I'm reading the JSON string from a textbox and then deserializing using the following
string json = textBox1.Text;
DataSet dataSet = JsonConvert.DeserializeObject<DataSet>(json);
I'm not at all familiar with DataSet, but after playing around with it a bit, I think I've found the reason. According to the documentation:
The DataSet consists of a collection of DataTable objects
Because a DataSet is a collection of objects, you can only deserialize a collection (array) into it. So,
{"items":[{"id":"1122267","quantity":"1","bundle":"1"}],"seconds_ago":"1"}
will not work, because it contains one collection (of items) and one property (seconds_ago). On the other hand,
{"items":[{"id":"1122267","quantity":"1","bundle":"1"}]}
works, because it only contains one collection.
Therefore, if you really want to deserialize your json string into a DataSet, you should do this instead:
{
"objects": [
{
"items":[{"id":"1122267","quantity":"1","bundle":"1"}],
"seconds_ago":"1"
}
]
}
You should really consider deserializing into a C# object though, which in my opinion is less complicated and easier to handle:
public class RootObject
{
public List<Item> items { get; set; }
public string seconds_ago { get; set; }
}
public class Item
{
public string id { get; set; }
public string quantity { get; set; }
public string bundle { get; set; }
}
RootObject deserializedObject = JsonConvert.DeserializeObject<RootObject>(json);
The DataSet class does not have a property seconds_ago or items. So therefore
DataSet dataSet = JsonConvert.DeserializeObject<DataSet>(json);
Will never work because you cannot convert that particular json string to a DataSet
i am working with json.net to deserialize json -> C# objects.
it works great in most cases but there are times where rather than getting an array i get object.
so my class (generated using http://json2csharp.com/ and modified to add property).
where i more than 1 arrival methods (such as pick up or ship) it works fine.
public class ArrivalMethods
{
[JsonProperty(PropertyName = "ArrivalMethod")]
public List<string> ArrivalMethod { get; set; }
}
but it breaks where there only 1 arrival method in the json response from my service because i believe json.net is expecting an object like below.
public class ArrivalMethods
{
[JsonProperty(PropertyName = "ArrivalMethod")]
public string ArrivalMethod { get; set; }
}
i am new to json etc. so i am not sure what i am doing wrong. but this throws exception.
Error converting value \"Ship\" to type 'System.Collections.Generic.List`1[System.String]'.
Path 'ProductDetail.SoftHardProductDetails.Fulfillment.
ArrivalMethods.ArrivalMethod', line 1, position 113."
here is where it breaks:
"ArrivalMethods":{
"ArrivalMethod":"Ship"
},
Your JSON should contain [] where there is a list. And if I'm understanding your answer correct, the first class example is the way you want to end up? If so you need the JSON on the bottom to mark ArrivalMethod as a list, wich its not now.
"ArrivalMethods":
{
"ArrivalMethod":["Ship"]
},
To be honest i get a little confused when there is a list with no plural ending.
If you can change the response format that would be the best. It really looks like XML semantics converted to JSON...
If you can't change the response format, you can try to use JsonConverterAttribute to create custom converters for those properties.