Deserealizing JSON object using Newtonsoft.Json - c#

I have API endpoint, that returning my JSON Object
Here is it
{
"results": [
{
"id": 182,
"title": "1-Day Private Beijing Tour to Tian'anmen Square, Forbidden City and Badaling Great Wall",
"price": "162",
"duration": "8",
"duration_type": "1",
"cover_image": {
"id": 308,
"img_path": "upload/images",
"img_file": "6d637884086151b30fe12db52fbaf5eb.jpg",
"status": "",
"created_at": "2018-02-27 02:25:36",
"updated_at": "2018-02-27 02:25:36",
"destination_id": "182",
"is_cover": "0",
"url": "https://api.xplorpal.com/upload/images/300x300/6d637884086151b30fe12db52fbaf5eb.jpg"
}
},
{
"id": 183,
"title": "One Day Private Beijing Tour to Mutianyu Great Wall and Summer Palace ",
"price": "197",
"duration": "8",
"duration_type": "1",
"cover_image": {
"id": 305,
"img_path": "upload/images",
"img_file": "1f8a09ddffb80ef9232f3511893ae5c4.jpg",
"status": "",
"created_at": "2018-02-27 02:22:19",
"updated_at": "2018-03-01 23:01:55",
"destination_id": "183",
"is_cover": "0",
"url": "https://api.xplorpal.com/upload/images/300x300/1f8a09ddffb80ef9232f3511893ae5c4.jpg"
}
}
]
}
I need to deserialize it
So I wrote this model
public class CoverImage
{
public int id { get; set; }
public string img_path { get; set; }
public string img_file { get; set; }
public string status { get; set; }
public string created_at { get; set; }
public string updated_at { get; set; }
public string destination_id { get; set; }
public string is_cover { get; set; }
public string url { get; set; }
}
public class Result
{
public int id { get; set; }
public string title { get; set; }
public string price { get; set; }
public string duration { get; set; }
public string duration_type { get; set; }
public CoverImage cover_image { get; set; }
}
public class RootObject
{
public List<Result> results { get; set; }
}
And trying to this like this
var responseExperiences = JsonConvert.DeserializeObject<IEnumerable<RootObject>>(content);
But when I run the project, I have this error:
Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.IEnumerable`1[TravelApp.Models.GettingExperiences+Results]' 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.
How I can fix this?

your JSON shows one object result corresponding to RootObject.
But you are trying to deserialize an array (IEnumerable<>) of RootObject
You should use this to deserialiaze the JSON showed :
JsonConvert.DeserializeObject<RootObject>(content);

Your API returns an object with a single property named result, not a collection. You should deserialize into a RootObject object.

Your api return single object named result not a collection you simply need to desearilize as a single object like.
var responseExperiences = JsonConvert.DeserializeObject<RootObject>(content);

Related

Exception occurs while deserialize json containing date with different format C#

Having json string containing date field
{
"totalSize": 2,
"records": [
{
"Id": "5006C000008ZhEDQA0",
"CreatedDate": "2021-12-01T15:14:20.000+0000",
"CaseNumber": "01378682",
"Status": "Open"
},
{
"Id": "5006C000008ZhE00A0",
"CreatedDate": "2021-12-05T08:00:00.000+0000",
"CaseNumber": "01378692",
"Status": "Open"
}
]
}
I'm trying to do normal Deserialization where CreatedDate datatype is DateTime.
JsonSerializer.Deserialize<SFHistoryResponse>(stringResponse);
I'm getting
The JSON value could not be converted to System.DateTime. Path:
$.records[0].CreatedDate
is there any way to format JSON's date part before Deserialization
The Newtonsoft JSON library can deserialize the string properly without throwing an exception:
using Newtonsoft.Json;
var response = JsonConvert.DeserializeObject<SFHistoryResponse>(stringResponse);
In your case your classes need to be:
public class Record
{
public string Id { get; set; }
public DateTime CreatedDate { get; set; }
public string CaseNumber { get; set; }
public string Status { get; set; }
}
public class SFHistoryResponse
{
public int totalSize { get; set; }
public List<Record> records { get; set; }
}
and when you try to deserialize the json
SFHistoryResponse l = JsonConvert.DeserializeObject<SFHistoryResponse>(jsonString);
tested my self
tbResult.Text = "l.records[0].CreatedDate.ToString() - " + l.records[0].CreatedDate.ToString();

Having issues reading a JSON file in C#

I am a novice in C# and I am having issues reading a JSON file.
The JSON file follows this format:
{
"info": {
"year": 2020,
"version": "1.0",
"description": "fake description",
"date_created": "2020-04-31T20:32:11.8958473Z"
},
"licenses": [
{
"name": "fake name",
"id": 2020
}
],
"images": [
{
"id": 1,
"width": 1280,
"height": 720,
"filename": "filename1.jpeg",
"license": 1
},
{
"id": 2,
"width": 1280,
"height": 720,
"filename": "filename2.jpeg",
"license": 2
},
...
For now I am trying to read the Images section in the JSON file. Here is my class for it:
public class Images
{
[JsonProperty("id")]
public int id { get; set; }
[JsonProperty("width")]
public int width { get; set; }
[JsonProperty("height")]
public int height { get; set; }
[JsonProperty("filename")]
public string filename { get; set; }
[JsonProperty("license")]
public int license { get; set; }
}
public class Image_json
{
[JsonProperty("images")]
public Image Image_json { get; set; }
}
In my main class, I try deserializing it here:
using System;
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
namespace C__Playground
{
public class read_json
{
static void Main(string[] args)
{
using (StreamReader r = new StreamReader("COCOExport.json"))
{
string json = r.ReadToEnd();
var test1 = JsonConvert.DeserializeObject<List<Image_json>(json);
}
}
}
}
When I try to run the program, I get this message:
Unhandled exception. Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[C__Playground.Image_jsonJson]' 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.
I have been following this post here.
I tried using the solution here but it returns empty or I receive a null error. Any insights?
Your problem should be here:
public class Image_json
{
[JsonProperty("images")]
public Image_json Image_json { get; set; }
}
This property is of type Image_json, which is the same as the containing class. You need a collection of Images. Could be an array or a List<Images>.
public class Image_json
{
[JsonProperty("images")]
public List<Images> Image_json { get; set; }
}
BTW, the Images class should be called Image since it holds a single image, not a collection of them.
Please find below code.
Class Images:
public class Images
{
[JsonProperty("id")]
public int id { get; set; }
[JsonProperty("width")]
public int width { get; set; }
[JsonProperty("height")]
public int height { get; set; }
[JsonProperty("filename")]
public string filename { get; set; }
[JsonProperty("license")]
public int license { get; set; }
}
class ImageJson:
public class ImageJson
{
[JsonProperty("images")]
public List<Images> Image_json // We shoild use list of images
{
get; set;
}
}
To test output:
using (StreamReader r = new StreamReader("COCOExport.json"))
{
string json = r.ReadToEnd();
var test1 = JsonConvert.DeserializeObject<ImageJson>(json);
foreach(var output in test1.Image_json)
{
Console.WriteLine(output.id);
Console.WriteLine(output.width);
Console.WriteLine(output.height);
Console.WriteLine(output.filename);
Console.WriteLine(output.license);
}
Console.ReadLine();
}
It is alwasy good practice to use PascalCasing for Properties.
Ex:)
[JsonProperty("id")]
public int Id { get; set; }
Please find solution here. Explained in a video
https://www.youtube.com/watch?v=nHtdReIhvag

Json Deserialize Array

I am new to Json and trying to do some examples with it. I have Json data like this:
{
"Title": "The Avengers",
"Year": "2012",
"Rated": "PG-13",
"Released": "04 May 2012",
"Runtime": "143 min",
"Genre": "Action, Adventure, Sci-Fi",
"Director": "Joss Whedon",
"Writer": "Joss Whedon (screenplay), Zak Penn (story), Joss Whedon (story)",
"Actors": "Robert Downey Jr., Chris Evans, Mark Ruffalo, Chris Hemsworth",
"Plot": "Earth's mightiest heroes must come together and learn to fight as a team if they are going to stop the mischievous Loki and his alien army from enslaving humanity.",
"Language": "English, Russian, Hindi",
"Country": "USA",
"Awards": "Nominated for 1 Oscar. Another 38 wins & 79 nominations.",
"Poster": "https://m.media-amazon.com/images/M/MV5BNDYxNjQyMjAtNTdiOS00NGYwLWFmNTAtNThmYjU5ZGI2YTI1XkEyXkFqcGdeQXVyMTMxODk2OTU#._V1_SX300.jpg",
"Ratings": [
{
"Source": "Internet Movie Database",
"Value": "8.0/10"
},
{
"Source": "Rotten Tomatoes",
"Value": "92%"
},
{
"Source": "Metacritic",
"Value": "69/100"
}
],
"Metascore": "69",
"imdbRating": "8.0",
"imdbVotes": "1,200,683",
"imdbID": "tt0848228",
"Type": "movie",
"DVD": "25 Sep 2012",
"BoxOffice": "$623,279,547",
"Production": "Walt Disney Pictures",
"Website": "http://marvel.com/avengers_movie",
"Response": "True"
}
I can get the data and read it just fine but when it comes deserialize I get the following error:
Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[Deneme.Modeller.Main]' 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.
This is my code
string url = "http://www.omdbapi.com/?apikey=7663ce8e&t=Avengers";
WebRequest request = WebRequest.Create(url);
WebResponse reply;
reply = request.GetResponse();
StreamReader returninfo = new StreamReader(reply.GetResponseStream());
string getinfo = returninfo.ReadToEnd();
List<Main> Info = JsonConvert.DeserializeObject<List<Main>>(getinfo);
and for models this is first main:
public string Title { get; set; }
public string Year { get; set; }
public string Rated { get; set; }
public string Released { get; set; }
public string Runtime { get; set; }
public string Genre { get; set; }
public string Director { get; set; }
public string Writer { get; set; }
public string Actors { get; set; }
public string Plot { get; set; }
public string Language { get; set; }
public string Country { get; set; }
public string Awards { get; set; }
public string Poster { get; set; }
public List<Rating> Ratings { get; set; }
public string Metascore { get; set; }
public string imdbRating { get; set; }
public string imdbVotes { get; set; }
public string imdbID { get; set; }
public string Type { get; set; }
public string DVD { get; set; }
public string BoxOffice { get; set; }
public string Production { get; set; }
public string Website { get; set; }
public string Response { get; set; }
second one is for Ratings:
public string Source { get; set; }
public string Value { get; set; }
public virtual ICollection<Main> Mains { get; set; }
It's about Json array, but I looked asked questions about this problem and tried to fix it but no luck. What am I missing?
You are trying to deserialize a single object of type Main into a list of objects.
You can either change your code to deserialize into a single object instead of a list or you can alter your JSON to represent an array of objects.
The first option would be
Main Info = JsonConvert.DeserializeObject<Main>(getinfo);
And the second option
[{"Title":"The Avengers","Year":"2012","Rated":"PG-13","Released":"04 May 2012","Runtime":"143 min","Genre":"Action, Adventure, Sci-Fi","Director":"Joss Whedon","Writer":"Joss Whedon (screenplay), Zak Penn (story), Joss Whedon (story)","Actors":"Robert Downey Jr., Chris Evans, Mark Ruffalo, Chris Hemsworth","Plot":"Earth's mightiest heroes must come together and learn to fight as a team if they are going to stop the mischievous Loki and his alien army from enslaving humanity.","Language":"English, Russian, Hindi","Country":"USA","Awards":"Nominated for 1 Oscar. Another 38 wins & 79 nominations.","Poster":"https://m.media-amazon.com/images/M/MV5BNDYxNjQyMjAtNTdiOS00NGYwLWFmNTAtNThmYjU5ZGI2YTI1XkEyXkFqcGdeQXVyMTMxODk2OTU#._V1_SX300.jpg","Ratings":[{"Source":"Internet Movie Database","Value":"8.0/10"},{"Source":"Rotten Tomatoes","Value":"92%"},{"Source":"Metacritic","Value":"69/100"}],"Metascore":"69","imdbRating":"8.0","imdbVotes":"1,200,683","imdbID":"tt0848228","Type":"movie","DVD":"25 Sep 2012","BoxOffice":"$623,279,547","Production":"Walt Disney Pictures","Website":"http://marvel.com/avengers_movie","Response":"True"}]
(simply add brackets)
Which option you have to choose is depending on your requirements, i.e. if you want to allow multiple objects or just one.
Main Info = JsonConvert.DeserializeObject<Main>(getinfo);
Your json string has only one Main object, you were trying to get a List
You try to deserialize one JSON object into a list of objects.
This is an example of simple object:
{ "field": 123 }
To deserialize it you need to:
var obj = JsonConvert.DeserializeObject<SomeModel>(json);
But if you have an array of objects:
[{ "field": 123 }, { "field": 123 }]
You will be able to deserialize them to a list like this:
var objs = JsonConvert.DeserializeObject<SomeModel[]>(json);
or
var objs = JsonConvert.DeserializeObject<List<SomeModel>>(json);
Solutions to your question:
Change deserialization type to a single object.
Wrap your JSON around with []
when we call api 'http://www.omdbapi.com/?apikey=7663ce8e&t=Avenger' we gets an objet not an array of object
try
var info = JsonConvert.DeserializeObject<Main>(getinfo);
If you want list of movies try a other api b.e.: themoviedbAPI

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.

Categories

Resources