Exception thrown when deserializing json with JSON.NET - c#

I have the following class
public class Airport
{
[MaxLength(75)]
public string Name { get; set; }
public bool NotInUse { get; set; }
[MaxLength(50)]
public string City { get; set; }
[MaxLength(50)]
public string Country { get; set; }
[MaxLength(2)]
public string Iso { get; set; }
[MaxLength(3)]
public string Iata { get; set; }
[MaxLength(4)]
public string Icao { get; set; }
}
I have the following json file - Not all properties are within the json
{
"Airports":{
[
{
"Name": "Belfast International",
"City": "Belfast",
"Country": "United Kingdom",
"Iso": "GB",
"Iata": "BFS"
},
{
"Name": "City of Derry",
"City": "Derry",
"Country": "United Kingdom",
"Iso": "GB",
"Iata": "LDY"
}
]
}
}
I am trying to deserialise the json with this method
public IList<Airport> ReadAirportsFromJson()
{
if (File.Exists(AirportJsonFilename))
{
string fileContents = File.ReadAllText(AirportJsonFilename);
var airports = JsonConvert.DeserializeObject<List<Airport>>(fileContents);
return airports;
}
return null;
}
I get the following exception
I am unsure how to progress this and resolve the issue.

The json is not valid, I'd suggest changing it to something like this
{
"Airports":
[
{
"Name": "Belfast International",
"City": "Belfast",
"Country": "United Kingdom",
"Iso": "GB",
"Iata": "BFS"
},
{
"Name": "City of Derry",
"City": "Derry",
"Country": "United Kingdom",
"Iso": "GB",
"Iata": "LDY"
}
]
}
and create a wrapper class
public class AirportsWrapper
{
public List<Airport> Airports { get; set; }
}
You can deserialize the json into AirportsWrapper and return the Airports property
public IList<Airport> ReadAirportsFromJson()
{
if (File.Exists(AirportJsonFilename))
{
string fileContents = File.ReadAllText(AirportJsonFilename);
var airportsWrapper = JsonConvert.DeserializeObject<AirportsWrapper>(fileContents);
if (airportsWrapper != null)
{
return airportsWrapper.Airports;
}
}
return null;
}
Demo: https://dotnetfiddle.net/NQ8JfQ

When passing it in like you do there, you're trying to deserialize the entire file into a list of airports. If the entire file is something else that also happens to contain a list of airports, this won't work. You either have to get just the parts of the JSON which is actually the list of airports, or you have to make a class/classes to represent the entire JSON file and deserialize into that. From there on, you can just go to yourObject.Airports.

Related

Nested item in json array is not being deserialized

I am trying to deserialize a json string from an api.
All works except for a nested item - Location which always ends up null
This is the string structure:
[
{
"CompanyProfile": "<p>A&B Inc etc...</p>",
"Address": "56 Test Street, Test, UK",
"Location": {
"Latitude": 61.52787,
"Longitude": -4.32095,
"Zoom": 13,
"Icon": null,
"Format": 0,
"Api": null,
"SearchTyped": null
},
"Id": 1723,
"Name": "A&B Inc"
},
{
"CompanyProfile": "<p>B&C Inc etc...</p>",
"Address": "57 Test Street, Test, UK",
"Location": {
"Latitude": 61.2122,
"Longitude": -4.31111,
"Zoom": 13,
"Icon": null,
"Format": 0,
"Api": null,
"SearchTyped": null
},
"Id": 1723,
"Name": "B&C Inc"
},
]
These are the classes to map to:
public class MemberDto
{
public int Id { get; set; }
public string? Name { get; set; }
public string? CompanyProfile { get; set; }
public string? Address { get; set; }
public Location? Location { get; internal set; }
}
public class Location
{
public decimal Latitude { get; set; }
public decimal Longitude { get; set; }
}
This is the deserialize code:
var result = await response.Content.ReadAsStringAsync();
var members = JsonConvert.DeserializeObject<List<MemberDto>>(result);
I know I can use ReadFromJsonAsync<List<MemberDto>>() as well but using ReadFromString so I can check the json before deserializing. Anyway the result is exactly the same for ReadFromJsonAsync.
Everything except Location is deserialized successfully
Anyone know what the issue is?
Remove the internal access modifier in the setter of Location.
public Location? Location { get; set; }

Deserialize Json with class names that are not always the same, in C#

I'm trying to deserialize a response from a firebase realtime database get/json, to get user locations that are online
example response:
{
"test1": {
"id": "test-1",
"location": {
"lat": 37.33097983,
"long": -122.03063943
}
},
"test2": {
"id": "test-2",
"location": {
"lat": 37.33021864,
"long": -122.02370753
}
},
"test3": {
"id": "test-3",
"location": {
"lat": 37.32873847,
"long": -122.01980584
}
},
"test4": {
"id": "test-4",
"location": {
"lat": 37.32563464,
"long": -122.01972943
}
},
"test5": {
"id": "test-5",
"location": {
"lat": 37.32472734,
"long": -122.02127163
}
}
}
I put this into a json to c# class converter and it creates a class for each user (Test1, Test2, Test3, etc). This would work, if the users from the example are the only users to be in the response. If I had a sixth user named "6test", I would need to also create a class for that one too.
How can I use the Json converter (Newtonsoft.Json or System.Text.Json) to return a user in a list<User>
you can use a dictionary in your case
using Newtosoft.Json;
Dictionary<string,Test> tests = JsonConvert.DeserializeObject<Dictionary<string,Test>>(json);
classes
public class Location
{
public double lat { get; set; }
public double #long { get; set; }
}
public class Test
{
public string id { get; set; }
public Location location { get; set; }
}
how to use
Test test5=tests["test5"];
or if you want to use list instead of Dictionary
var jsonParsed = JObject.Parse(json);
List<ListTest> list = jsonParsed.Properties().Select(p => new ListTest { Name = p.Name, Test = p.Value.ToObject<Test>() }).ToList();
how to use
Test test4 = list.Where(f=>f.Name=="test4").Select(t=>t.Test).FirstOrDefault();
class
public class ListTest
{
public string Name { get; set; }
public Test Test { get; set; }
}

Deserialzise JSON with only parts of needed model information in ASP.NET Core 3

do I always need to create a model for an incoming JSON and then deserialize the JSON to it or is there a way to loop through the JSON file, check specific properties and add additional information?
Here is why I ask:
In my project I have two classes "region" and "country". Inside "region" is the nested class "country"
enter code here
public class Region`enter code here`
{
[Key]
public int Id { get; set; }
public string Region { get; set; }
public Country Country { get; set; }
}
public class Country
{
[Key]
public int Id { get; set; }
[Required]
[MaxLength(255)]
public string Name { get; set; }
[Required]
[MaxLength(2)]
public string ISO3166Alpha2 { get; set; }
[Required]
[MaxLength(3)]
public string ISO3166Alpha3 { get; set; }
}
Now I have an incoming JSON which has the country and region information which i need but without Ids or any other required information.
So do i need to create a new model, deserialize the JSON and then use that new model to create my "region" and "country" model or is there a better way of doing this?
{
"regions": [
{
"country": "France",
"region": [
"Bordeaux",
"Burgundy",
"Beaujolais",
"Champagne",
"Loire",
"Alsace",
"Rhône",
"Provence",
"Languedoc-Roussillon",
"Jura"
]
},
{
"country": "Italy",
"region": [
"Piedmont",
"Barolo",
"Barbaresco",
"Tuscany",
"Veneto",
"Friuli-Venezia",
"Giulia",
"Abruzzo",
"Sicily",
"Lambrusco"
]
}
}
´´´
Thanks a lot :)
kindly find below the way to achieve that as stated by the docs. kindly visit this link https://www.newtonsoft.com/json/help/html/DeserializeAnonymousType.htm but however my solution is shown below.
var json1 = #"{
'regions': [
{
'country': 'France',
'region': [
'Bordeaux',
'Burgundy',
'Beaujolais',
'Champagne',
'Loire',
'Alsace',
'Rhône',
'Provence',
'Languedoc-Roussillon',
'Jura'
]
},
{
'country': 'Italy',
'region': [
'Piedmont',
'Barolo',
'Barbaresco',
'Tuscany',
'Veneto',
'Friuli-Venezia',
'Giulia',
'Abruzzo',
'Sicily',
'Lambrusco'
]
}]}";
var definition = new { regions = new[]{new {country = "" , region = new string[]{ } } }};
var customer1 = JsonConvert.DeserializeAnonymousType(json1, definition);
Console.WriteLine(customer1.regions);
foreach (var item in customer1.regions)
{
Console.WriteLine(item.country);
}

How to deserialize json string in windows phone?

I just got my json response as a string.My json is given below,
"code": 0,
"message": "success",
"students": {
"details":{
"hjeke": {
"id": "257633000000070001",
"name": "hjeke",
"percentage": 36,
"type": "Good",
},
"Second": {
"id": "257633000000073001",
"name": "Second",
"percentage": 4,
"type": "bad",
}
}
}
Like hjeke and Second there are many key value pairs,how can i deserialize my json using Newtonsoft.json
Try to understand my solution in your previous question
How to deserialize json data in windows phone?
Your first JSON in that question was good and simple to use.
JSON, where field names are unique not convinient to deserialize. So, you got problems such as public class Hjeke and public class Second for each instance, when you use code generator.
Use JSON-structure with list of students:
"code": 0,
"message": "success",
"students": [
{
"id": "257633000000070001",
"name": "hjeke",
"percentage": 36,
"type": "Good",
},
{
"id": "257633000000073001",
"name": "Second",
"percentage": 4,
"type": "bad",
}]
is good and flexible structure. Using this, you don't need to parse not obvious fields like
"details":{
"hjeke": {
and so on.
And work with them using classes, from my previous answer. The main idea - you need list of objects. public List<StudentDetails> students. Then, all students objects deserialized in List, which is easy to use.
As everybody mentioned your json seems to be very unflexible, huh.
You can extract the data you are interested in.
So this is your model:
public class StudentDetails
{
public string id { get; set; }
public string name { get; set; }
public int percentage { get; set; }
public string type { get; set; }
}
And this is how you can extract it:
var jsonObj = JObject.Parse(str);
// get JSON result objects into a list
var results = jsonObj["students"]["details"].Children().Values();
// serialize JSON results into .NET objects
var details = new List<StudentDetails>();
foreach (JToken result in results)
{
var st = result.ToString();
var searchResult = JsonConvert.DeserializeObject<StudentDetails>(st);
details.Add(searchResult);
}
I'm using a newtonsoft.json library here.
Your Response string has some mistakes man, its not a valid json
just small modification to be done as below:
{
"code": 0,
"message": "success",
"students": {
"details": {
"hjeke": {
"id": "257633000000070001",
"name": "hjeke",
"percentage": 36,
"type": "Good"
},
"Second": {
"id": "257633000000073001",
"name": "Second",
"percentage": 4,
"type": "bad"
}
}
}
}
you can make out the difference
Now Follow these steps:
1.Go to this link Json to C#
2.place your Json string there and generate C# class object
3.Now create this class in your solution
4.Now deserialize As below
var DeserialisedObject = JsonConvert.DeserializeObject<Your Class>(YourJsonString);
First, create the classes:
public class Hjeke
{
public string id { get; set; }
public string name { get; set; }
public int percentage { get; set; }
public string type { get; set; }
}
public class Second
{
public string id { get; set; }
public string name { get; set; }
public int percentage { get; set; }
public string type { get; set; }
}
public class Details
{
public List<Hjeke> hjeke { get; set; }
public List<Second> Second { get; set; }
}
public class Students
{
public List<Details> details { get; set; }
}
public class RootObject
{
public int code { get; set; }
public string message { get; set; }
public List<Students> students { get; set; }
}
After that, use JSON.NET to deserialize:
var deserialized = JsonConvert.DeserializeObject<Class1>(YourStringHere);
Do you have any influence over the json response? Details should probably be a JSONArray in this case, not an object with a varying amount of properties, since I assume that's what you mean is the issue here.

Is this json format correct?

I have a json data when i'm trying to parse it returns error incorrect syntax please help me found the syntax error.
[{"isData":"Yes","Details":"[{"Id":"70","Name":"Test","FileName":"Uploaded","FileFormat":".mp4","FileType":"Video","FileDuration":"00:30:00 ","StartTime":"/Date(1372617000000)/","EndTime":"/Date(1372681771000)/","File":"2562013172331815635077778118152815.mp4"}]"}]
And this is the class that is used to serialize data, i am using javascript serializer
public enum Data
{
Yes,
No
}
public class MessageResponse()
{
public string isData { get; set; }
public string Details { get; set; }
}
List<MessageResponse> response = new List<MessageResponse>();
string strJson="[{"Id":"70","Name":"Test","FileName":"Uploaded","FileFormat":".mp4","FileType":"Video","FileDuration":"00:30:00 ","StartTime":"/Date(1372617000000)/","EndTime":"/Date(1372681771000)/","File":"2562013172331815635077778118152815.mp4"}]";
var newData = new MessageResponse
{
isData = Data.Yes.ToString(),
Details = strJson
};
response.Add(newData);
var jsonSerialiser1 = new JavaScriptSerializer();
string result = jsonSerialiser1.Serialize(response);
That's invalid JSON. The Details property is incorrectly formatted. You should remove the quotes around the value. It should be like this:
[
{
"isData": "Yes",
"Details": [
{
"Id": "70",
"Name": "Test",
"FileName": "Uploaded",
"FileFormat": ".mp4",
"FileType": "Video",
"FileDuration": "00:30:00 ",
"StartTime": "/Date(1372617000000)/",
"EndTime": "/Date(1372681771000)/",
"File": "2562013172331815635077778118152815.mp4"
}
]
}
]
or if you want Details to be a string property (representing JSON), which is kinda lame, you should properly escape the double quotes:
[
{
"isData": "Yes",
"Details": "[{\"Id\":\"70\",\"Name\":\"Test\",\"FileName\":\"Uploaded\",\"FileFormat\":\".mp4\",\"FileType\":\"Video\",\"FileDuration\":\"00: 30: 00\",\"StartTime\":\"/Date(1372617000000)/\",\"EndTime\":\"/Date(1372681771000)/\",\"File\":\"2562013172331815635077778118152815.mp4\"}]"
}
]
This structure you will be able to map to your current object model. But I would recommend you using the first approach.
Remove the " from the details data:
[{
"isData":"Yes",
"Details":
[{
"Id":"70",
"Name":"Test",
"FileName":"Uploaded",
"FileFormat":".mp4",
"FileType":"Video",
"FileDuration":"00:30:00",
"StartTime":"/Date(1372617000000)/",
"EndTime":"/Date(1372681771000)/",
"File":"2562013172331815635077778118152815.mp4"
}]
}]
Details should be of type class (i.e. user defined class) and it should hold all the properties.
public class Details
{ public int Id {get; set;} ... }
Firstly your json is invalid.
It should not have the " before and after the [ ]
[
{
"isData": "Yes",
"Details": [
{
"Id": "70",
"Name": "Test",
"FileName": "Uploaded",
"FileFormat": ".mp4",
"FileType": "Video",
"FileDuration": "00: 30: 00",
"StartTime": "/Date(1372617000000)/",
"EndTime": "/Date(1372681771000)/",
"File": "2562013172331815635077778118152815.mp4"
}
]
}
]
Secondly, your class could be improved to be:
public class MessageResponse
{
public string isData { get; set; }
public Details Details { get; set; }
}
public class Details
{
public int Id { get; set; }
public string Name { get; set; }
public string FileName { get; set; }
public string FileFormat { get; set; }
public string FileType { get; set; }
public string FileDuration { get; set; }
public string StartTime { get; set; }
public string EndTime { get; set; }
public string File { get; set; }
}
You would probably want to set up the correct data types though for things like Start Time etc...

Categories