Can not deserialize JSON with array in array - c#

How I should deserialize below JSON?
{
"lastUpdateId": 131537317,
"bids": [
["0.08400000", "0.54300000", []],
["0.08399800", "0.70800000", []],
["0.08399400", "1.22700000", []],
["0.08399300", "0.61700000", []],
["0.08399100", "0.35400000", []]
],
"asks": [
["0.08408300", "0.09100000", []],
["0.08408400", "5.55300000", []],
["0.08408600", "0.71800000", []],
["0.08408900", "0.14500000", []],
["0.08409000", "0.15100000", []]
]
}
I use classes like below. Ask and Bid are the same.
Order deserializedProduct = JsonConvert.DeserializeObject<Order>(timeServer);
public class Order
{
public int lastUpdateId { get; set; }
public List<Bid> bids { get; set; }
public List<Ask> asks { get; set; }
}
public class Bid
{
public List<string> Items { get; set; }
}
I have error:
Cannot deserialize the current JSON array (e.g. [1,2,3]) into type
'WebApplication2.Models.Bid' because the type requires a JSON object
(e.g. {"name":"value"}) to deserialize correctly. To fix this error
either change the JSON to a JSON object (e.g. {"name":"value"}) or
change the deserialized type to an array or a type that implements a
collection interface (e.g. ICollection, IList) like List that can
be deserialized from a JSON array. JsonArrayAttribute can also be
added to the type to force it to deserialize from a JSON array. Path
'bids[0]', line 1, position 35.

Better class to represent your JSON is:
public class Order
{
public int lastUpdateId { get; set; }
public List<List<object>> bids { get; set; }
public List<List<object>> asks { get; set; }
}
As #maccettura mentioned in his comment Bids and Asks are IEnumerable<IEnumerable<string>>

Related

Deserialize JSON in c# - what is wrong?

I'm trying without success to deserialize this JSON in c#:
{
"settings": {
"path": "http:\/\/www.igormasin.it\/fileuploads\/tanja_23a6id"
},
"files": [{
"file": "\/IMG_0992-Edit_a.jpg"
}, {
"file": "\/IMG_1024-Edit_a.jpg"
}, {
"file": "\/IMG_1074-Edit_a.jpg"
}, {
"file": "\/Untitled-1.jpg"
}]
}
my code:
public class JsonTxt
{
public IList<string> settings { get; set; }
public IList<string> files { get; set; }
}
downloadstring contains the Json text:
var deserialized = JsonConvert.DeserializeObject<JsonTxt>(downloadString);
Console.WriteLine("*************************************************");
Console.WriteLine(deserialized.settings[0].ToString());
Console.WriteLine(deserialized.files.Count);
exception:
Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the current JSON object (e.g.
{"name":"value"}) into type 'System.Collections.Generic.IList`1[System.String]' 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<T>) 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 'settings.path', line 1, position 20.'
I am not able to understand the error, and what I am suposed to do.. From what I understand IList is wrong, but what else would be the correct thing to write?
Your class structure needs to be something like this:
public class JsonTxt
{
public Settings Settings { get; set; }
public IList<File> Files { get; set; }
}
public class Settings
{
public string Path { get; set; }
}
public class File
{
public string File { get; set; }
}
Settings is an object, not a collection, and Files is a collection of objects not strings.
Your class type expect IList settings :
public class JsonTxt
{
public IList<string> settings { get; set; }
public IList<string> files { get; set; }
}
but in the json you provide is an object
"settings": {
"path": "http:\/\/www.igormasin.it\/fileuploads\/tanja_23a6id"
},
you should change JsonText attributes type to match with your JSON

.net core API sending array object

I have student class with array StudentPhones. When i remove StudentPhones property from Student class is working perfectly when post with Postman. But when add StudentPhones property then Postman gives me this error:
{
"StudentPhones": [
"Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'DataAccess.StudentPhone' because the type requires a JSON object (e.g. {\"name\":\"value\"}) to deserialize correctly.\r\nTo fix this error either change the JSON to a JSON object (e.g. {\"name\":\"value\"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.\r\nPath 'StudentPhones', line 4, position 23."
]
}
public class Student
{
public string StudentName { get; set; }
public string StudentSurname { get; set; }
public StudentPhone StudentPhones { get; set; }
}
public class StudentPhone
{
public int PhoneType{ get; set; }
public string PhoneNumber { get; set; }
}
public async Task<ServiceResult> SaveStudent([FromBody]Student student)
{
}
How can I post this json? (I am using angular 6 in real, postman is only for example.)
my json
{
"studentName": "test",
"studentSurname": "test",
"studentPhones": [
{
"phoneType": 1,
"phoneNumber ": "111111111"
},
{
"phoneType": 2,
"phoneNumber ": "2222222222"
}
],
}
You have an array of phones in your JSON, so instead of public StudentPhone StudentPhones { get; set; } in your model, you should have public List<StudentPhone> StudentPhones { get; set; }

C# deserialize multiple JSON collections into a single List<T>

I fetch a collection of collections of the same object from a web api.
I would then like to deserialize the JSON into a single List
The JSON is as follows:
{
"Liverpool": [
{
"playerId": "LIV01",
"name": "Adam Llana",
"position": "Midfielder"
},
{
"playerId": "LIV02",
"name": "Daniel Sturridge",
"position": "Forward"
}
],
"ManchesterUnited": [
{
"playerId": "MNU01",
"name": "Daley Blind",
"position": "Defender"
},
{
"playerId": "MNU02",
"name": "Romelu Lukaku",
"position": "Forward"
}
],
"Arsenal": [
{
"playerId": "ARS01",
"name": "Petr Cech",
"position": "Goalkeeper"
},
{
"playerId": "ARS02",
"name": "Santi Cazorla",
"position": "Midfielder"
}
]
}
What I could like to be able to do is the following as I am not interested in the collection names:
public class Player
{
public string playerId { get; set; }
public string name { get; set; }
public string position { get; set; }
}
List<Player> cards = JsonConvert.DeserializeObject<List<Player>>(jsonContent);
This does not work and produces an error.
Cannot deserialize the current JSON object (e.g. {\"name\":\"value\"})
into type 'System.Collections.Generic.List`1[Player]' 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.
Is there any way to accomplish this using Newtonsoft.Json?
Because of the variable team names you need to deserialize into Dictionary<string, List<Player>>. From there use SelectMany on the values of the dictionary to get the players
public class Player
{
public string playerId { get; set; }
public string name { get; set; }
public string position { get; set; }
}
var teams = JsonConvert.DeserializeObject<Dictionary<string, List<Player>>>(jsonContent);
List<Player> players = teams.SelectMany(kvp => kvp.Value).ToList();
What you want is to deserialize that object as a dictionary:
var teams = JsonConvert.DeserializeObject<Dictionary<string, List<Player>>>(jsonContent);
The original object isn't an array so it doesn't make sense to deserialize it as an array or a List<T>
Later, if you want only the player list and don't care about the club names, then just use LINQ's SelectMany to flatten the dictionary:
var allPlayers = teams.SelectMany(entry => entry.Value);
If you simply try to create an object for players right now it won't work as the team names are unique. Your class to deserialize should look like this:
public class Teams
{
public Liverpool[] Liverpool { get; set; }
public Manchesterunited[] ManchesterUnited { get; set; }
public Arsenal[] Arsenal { get; set; }
}
public class Liverpool
{
public string playerId { get; set; }
public string name { get; set; }
public string position { get; set; }
}
public class Manchesterunited
{
public string playerId { get; set; }
public string name { get; set; }
public string position { get; set; }
}
public class Arsenal
{
public string playerId { get; set; }
public string name { get; set; }
public string position { get; set; }
}
Now you can straight away deserialize the data to this object.
Teams teams = JsonConvert.DeserializeObject<Teams>(jsonContent);
Their is an option know as Paste Special inside the Edit option in the top File Menu, this option lets you create classes that mimics the properties of a json or xml.

Cannot deserialize the current JSON array when returned value can be either array or single item

I am new to Newtonsoft.Json so please excuse my ignorance - however I am coming up against this issue when trying to Deserialize the following Json to either a c# object or indeed manually.
The Json is
{
"travellerInfo": [
{
"passengerData": {
"travellerInformation": {
"passenger": [
{
"type": "ADT",
"firstName": "MARY MRS"
},
{
"type": "INF",
"firstName": "JOSHUA"
}
],
"traveller": {
"surname": "SMITH",
"quantity": "2"
}
}
}
},
{
"passengerData": {
"travellerInformation": {
"passenger": {
"type": "ADT",
"firstName": "JOHN MR"
},
"traveller": {
"surname": "SMITH",
"quantity": "1"
}
}
}
}
]
}
So as you can see, on the first 'passenger' item, this returns as an Array, however on the second 'passenger' item, it doesn't return as an array, just a single block. I am not in control of the Json being sent to me - it comes from an external system. My C# classes are
public class Passenger
{
public string type { get; set; }
public string firstName { get; set; }
}
public class Traveller
{
public string surname { get; set; }
public string quantity { get; set; }
}
public class TravellerInformation
{
public List<Passenger> passenger { get; set; }
public Traveller traveller { get; set; }
}
public class PassengerData
{
public TravellerInformation travellerInformation { get; set; }
}
public class TravellerInfo
{
public PassengerData passengerData { get; set; }
}
and I call
var example = JsonConvert.DeserializeObject<TravellerInfo>(jsonString);
I am getting the error
Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'Script1.TravellerInfo' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List<T> that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.
Path 'travellerInfo', line 57, position 20.
I tried putting a [JsonArray] attribute on the Passenger class to force it to deserialise as an array/list, but same error occured as I think the underlying item is a JProperty instead of a JObject.
So how can I get this to work when the ["passenger"] can come back as both an Array and Single object ?
Cheers in Advance
You can try deserialize it as dynamic and then do some checks to types. Check if it is IEnumerable.
That should do the job.
Try this. Replace List<Passenger> with object passenger in TravellerInformation:
public class Traveller
{
public string surname { get; set; }
public string quantity { get; set; }
}
public class TravellerInformation
{
public object passenger { get; set; }
public Traveller traveller { get; set; }
}
public class PassengerData
{
public TravellerInformation travellerInformation { get; set; }
}
public class TravellerInfo
{
public PassengerData passengerData { get; set; }
}
And call this by passing List<TravellerInfo> instead of TravellerInfo:
var example = JsonConvert.DeserializeObject<List<TravellerInfo>>(jsonString);
Also for these cases you can use this service which automatically creates C# classes from JSON objects, so you don't have to worry about correctness.

Using JSON.net to deserialize a list of nested objects

Thanks in advance for your help.
I have a JSON file that contains a list of nested objects. Using the code below - I get an exception on the call to DeserializeObject. We are using JSON.net
Any help is appreciated
JSON:
[
{
"Email": "james#example.com",
"Active": true,
"CreatedDate": "2013-01-20T00:00:00Z",
"Input": {
"User": "Jim",
"Admin": "John"
},
"Output": {
"Version": "12345",
"Nylon": "None"
}
},
{
"Email": "bob#example.com",
"Active": true,
"CreatedDate": "2013-01-21T00:00:00Z",
"Input": {
"User": "Bob",
"Admin": "John"
},
"Output": {
"Version": "12399",
"Nylon": "134"
}
}
]
To support the deserialization I have created the following class structure.
public class Test002
{
public class Input
{
public string User { get; set; }
public string Admin { get; set; }
}
public class Output
{
public string Version { get; set; }
public string Nylon { get; set; }
}
public class RootObject
{
public string Email { get; set; }
public bool Active { get; set; }
public DateTime CreatedDate { get; set; }
public Input input { get; set; }
public Output output { get; set; }
}
public class TestCases
{
public List<RootObject> rootObjects { get; set; }
}
}
And finally here is the call to JSON.net JsonConvert.DeserializeObject - throws the following exception.
Test002.TestCases tTestCases = JsonConvert.DeserializeObject<Test002.TestCases>(File.ReadAllText(#"C:\test\Automation\API\Test002.json"));
I think I need something like this - to deseralize the list of objects - The code below fails
Test002.TestCases tTestCases = JsonConvert.DeserializeObject<IList<Test002.TestCases>>(File.ReadAllText(#"C:\test\Automation\API\Test002.json"));
Exception:
An exception of type 'Newtonsoft.Json.JsonSerializationException' occurred in Newtonsoft.Json.dll but was not handled in user code
Additional information: Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'APISolution.Test002+TestCases' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.
Path '', line 1, position 1.
Why don't change TestCases to be a list? Works perfectly.
public class TestCases : List<RootObject> {}
The issue here is that you're trying to deserialize into an IList. IList is an interface, not a concrete type so JSON.NET doesn't know what to create. You need to tell it the exact type you want:
List<Test002.TestCases> tTestCases = JsonConvert.DeserializeObject<List<Test002.TestCases>>(File.ReadAllText(#"C:\test\Automation\API\Test002.json"));
You could cast that into an IList like this:
IList<Test002.TestCases> tTestCases = JsonConvert.DeserializeObject<List<Test002.TestCases>>(File.ReadAllText(#"C:\test\Automation\API\Test002.json"));
Perhaps try something as simple as this:
var tTestCases = JsonConvert.DeserializeObject<Test002.RootObject[]>(File.ReadAllText(#"C:\test\Automation\API\Test002.json"));
According to the json-data specified, you got some IEnumerable of RootObjects.
Your classes are well-composed, except the Test002 class. Everything should be OK if you try to deserialize json-data as List. Try something like
var result = JsonConvert.DeserializeObject<List<RootObject>>(File.ReadAllText(#"C:\test\Automation\API\Test002.json"));
If you strongly need the instance of your Test002 class, you should use
Test002.TestCases result = new TestCases(){
rootObjects = JsonConvert.DeserializeObject<List<RootObject>(File.ReadAllText(#"C:\test\Automation\API\Test002.json"))
};

Categories

Resources