Json Deserialize Array - c#

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

Related

Deserializing a serialized JSON file

I have a JSON file that has been serialized through an API, in which I need to deserialize it to use the data it generated in my code. The issue is that I'm getting an Exception Unhandled error in which I have tried to understand the solution to the error, but I have had a few days off tunnel vision with this issue.
I have tried my best to link my issue with other threads, but have been lost for a few days. I did get some form of sprint finish with setting up a {get { return } } with a property but due to the setup of the code when serializing I couldn't do that. Instead I've tried to put the file outputted in a simple location and tried desalinizing it based on the file location.
ImageModeration image1 = JsonConvert.DeserializeObject<ImageModeration>(File.ReadAllText(#"C:\ModerationOutput.json"));
// deserialize JSON directly from a file
using (StreamReader file = File.OpenText(#"C:\ModerationOutput.json"))
{
JsonSerializer serializer = new JsonSerializer();
ImageModeration image2 = (ImageModeration)serializer.Deserialize(file, typeof(ImageModeration));
}
Here is my json file
[
{
"ImageUrl": "URL",
"ImageModeration": {
"CacheID": "396a972f-79ae-4b31-a54c-0ba3314318fa_637026883058218816",
"Result": false,
"TrackingId": "UKS_ibiza_464a60be-f57d-4ee1-aa37-13d04f151fdd_ContentModerator.F0_4ae15371-36c9-4cb2-8e21-83381a29432c",
"AdultClassificationScore": 0.0048455675132572651,
"IsImageAdultClassified": false,
"RacyClassificationScore": 0.011258091777563095,
"IsImageRacyClassified": false,
"AdvancedInfo": [
{
"Key": "ImageDownloadTimeInMs",
"Value": "37"
},
{
"Key": "ImageSizeInBytes",
"Value": "34854"
}
],
"Status": {
"Code": 3000,
"Description": "OK",
"Exception": null
}
},
"TextDetection": null,
"FaceDetection": null
}
]
This error comes from the first line of code.
Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the
current JSON array (e.g. [1,2,3]) into type
'convertingJSON.Program+ImageModeration' 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.'
Specific to your JSON string that you have posted, you can refer to the following code snippet to deserialize your string into its respective components.I am using the Newtonsoft JSON library which is a popular high-performance JSON framework for .NET. A working example can be found at: https://dotnetfiddle.net/RmXNHM
using System;
using Newtonsoft.Json;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
string json=#"[{'ImageUrl':'URL','ImageModeration':{'CacheID':'396a972f-79ae-4b31-a54c-0ba3314318fa_637026883058218816','Result':false,'TrackingId':'UKS_ibiza_464a60be-f57d-4ee1-aa37-13d04f151fdd_ContentModerator.F0_4ae15371-36c9-4cb2-8e21-83381a29432c','AdultClassificationScore':0.004845567513257265,'IsImageAdultClassified':false,'RacyClassificationScore':0.011258091777563095,'IsImageRacyClassified':false,'AdvancedInfo':[{'Key':'ImageDownloadTimeInMs','Value':'37'},{'Key':'ImageSizeInBytes','Value':'34854'}],'Status':{'Code':3000,'Description':'OK','Exception':null}},'TextDetection':null,'FaceDetection':null}]";
var Sresponse = JsonConvert.DeserializeObject<List<RootObject>>(json);
foreach(var value1 in Sresponse)
{
Console.WriteLine(value1.ImageUrl);
Console.WriteLine(value1.ImageModeration.CacheID);
}
}
}
public class AdvancedInfo
{
public string Key { get; set; }
public string Value { get; set; }
}
public class Status
{
public int Code { get; set; }
public string Description { get; set; }
public object Exception { get; set; }
}
public class ImageModeration
{
public string CacheID { get; set; }
public bool Result { get; set; }
public string TrackingId { get; set; }
public double AdultClassificationScore { get; set; }
public bool IsImageAdultClassified { get; set; }
public double RacyClassificationScore { get; set; }
public bool IsImageRacyClassified { get; set; }
public List<AdvancedInfo> AdvancedInfo { get; set; }
public Status Status { get; set; }
}
public class RootObject
{
public string ImageUrl { get; set; }
public ImageModeration ImageModeration { get; set; }
public object TextDetection { get; set; }
public object FaceDetection { get; set; }
}
Output:
URL
396a972f-79ae-4b31-a54c-0ba3314318fa_637026883058218816
Use this site to convert you're JSON to a C# object and then deserialize to it.
According to the error it seems you may have been missing a property i.e. the object does not correspond to the JSON

Deserealizing JSON object using Newtonsoft.Json

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);

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.

C# Newtonsoft deserialize JSON array

I'm trying to deserialize an array using Newtonsoft so i can display files from a cloud based server in a listbox but i always end up getting this error no matter what i try:
Newtonsoft.Json.JsonReaderException: 'Unexpected character encountered while parsing value: [. Path '[0].priv', line 4, position 15.'
Thisis an example try to deserialize:
[
{
"code": 200,
"priv": [
{
"file": "file.txt",
"ext": "txt",
"size": "104.86"
},
{
"file": "file2.exe",
"ext": "exe",
"size": "173.74"
},
],
"pub": [
{
"file": "file.txt",
"ext": "txt",
"size": "104.86"
},
{
"file": "file2.exe",
"ext": "exe",
"size": "173.74"
}
]
}
]
I tried using a C# Class like this:
public class ListJson
{
[JsonProperty("pub")]
public List List { get; set; }
}
public class List
{
[JsonProperty("file")]
public string File { get; set; }
[JsonProperty("ext")]
public string Ext { get; set; }
[JsonProperty("size")]
public string Size { get; set; }
}
[JsonProperty("priv")]
public List List { get; set; }
}
public class List
{
[JsonProperty("file")]
public string File { get; set; }
[JsonProperty("ext")]
public string Ext { get; set; }
[JsonProperty("size")]
public string Size { get; set; }
}
And deserialize with:
List<list> fetch = Newtonsoft.Json.JsonConvert.DeserializeObject<List<list>>(json);
The correct C# class structure for your JSON is the following:
public class FileEntry
{
public string file { get; set; }
public string ext { get; set; }
public string size { get; set; }
}
public class FileList
{
public int code { get; set; }
public List<FileEntry> priv { get; set; }
public List<FileEntry> pub { get; set; }
}
Deserializing it in this way:
var fetch = JsonConvert.DeserializeObject<FileList[]>(json);
var fileList = fetch.First(); // here we have a single FileList object
As said in the other answer, creating a class called List doesn't automagically turn it into a collection of objects. You need to declare the types to be deserialized from an array a collection type (e.g. List<T>, T[], etc.).
Small tip: when in doubt, use json2csharp.com to generate strongly typed classes from a json string.
At the moment List has a single List instance called priv, which despite the name: doesn't make it a list. To deserialize a JSON array ("priv": [...]), it needs to an array or list-like type, for example List<T> for some T. Presumably a List<FileThing>, if we assume that FileThing is actually the second type called List (you have 2).

deserializing child data collections into ienumerables using JSON.NET

Current I have a project where I'm getting the following sample data ( I want to retrieve only the ids within this json string and stuff them into IEnumerables (explained below):
{
"states": [
{
"id": "AL",
"text": "Alabama (AL)"
},
{
"id": "CO",
"text": "Colorado (CO)"
}
],
"cities": [
{
"id": 71761,
"text": "New Brockton, AL"
},
{
"id": 74988,
"text": "Nathrop, CO"
}
],
"zipCodes": []
}
Notice in the zipCodes, I am getting an empty set, so there is no "id" or "text".
I want to be able to create several IEnumerables from the properties found in this JSON string.
I created an object called Locations that looks like this:
public class Location
{
public IEnumerable<string> States { get; set; }
public IEnumerable<string> ZipCodes { get; set; }
public IEnumerable<decimal> Cities { get; set; }
}
The best way I found to going about this approach is to do each data property one by one and convert, formValues is the json string:
JArray arrStates = (JArray)formValues["states"];
JArray arrCities = (JArray)formValues["cities"];
JArray arrZip = (JArray)formValues["zipCodes"];
and then set the properties in the location object as so:
Location loc = new Location();
loc.States = arrStates.Children().Select(m=>m["id"].Value<string>());
loc.ZipCodes = arrCities.Children().Select(m=>m["id"].Value<string>());
loc.Cities = arrZip.Children().Select(m=>m["id"].Value<string>());
I was wondering if there's a better way of doing this instead of doing all this code maintenance for whenever my json response adds a new property. In fact, I think there's going to be about ten more properties added to the json string.
I want it to be reduced down to where I could just update the Location object, and have the json automatically map to the properties that way. Or atleast a solution that has less maintenance than what I'm doing now.
Also I was wondering if JsonConvert.DeserializeObject would work in my case; but read that JSON.NET treats an IEnumerable as an array, so I'm stumped on this one.
JsonConvert.DeserializeObject would work in your case and it will have less maintenance than what you're doing now.
If you enter your json data to http://json2csharp.com, below is the generated class definition that you can use, I renamed RootObject to Location
public class State
{
public string id { get; set; }
public string text { get; set; }
}
public class City
{
public int id { get; set; }
public string text { get; set; }
}
public class Location
{
public List<State> states { get; set; }
public List<City> cities { get; set; }
public List<object> zipCodes { get; set; }
}
This is how you deserialize the json data into Location
string jsonData = ...; // set the json data here
var location = JsonConvert.DeserializeObject<Location>(jsonData);
You can enumerate through the nested properties to get the ids, for example location.states[0].id will return "AL" and location.cities[1].id will return 74988.
If there's a new property in the json data, let's say it's named countries with id and text like in states, you can create a new Country class
public class Country
{
public string id { get; set; }
public string text { get; set; }
}
and add countries property to Location class
public class Location
{
public List<State> states { get; set; }
public List<City> cities { get; set; }
public List<object> zipCodes { get; set; }
public List<Country> countries { get; set; }
}

Categories

Resources