I'm trying to parse out some information I've retrieved from RottenTomatoes that's in a JSON format
{
"cast": [
{
"id": "162655641",
"name": "Tom Hanks",
"characters": [
"Woody"
]
},
{
"id": "162655909",
"name": "Tim Allen",
"characters": [
"Buzz Lightyear"
]
},
{
"id": "162655020",
"name": "Joan Cusack",
"characters": [
"Jessie the Cowgirl"
]
},
{
"id": "162672460",
"name": "Ned Beatty",
"characters": [
"Lots-o'-Huggin' Bear",
"Lotso"
]
},
{
"id": "162657445",
"name": "Richard Kind",
"characters": [
"Bookworm"
]
},
{
"id": "162654813",
"name": "Erik von Detten",
"characters": [
"Sid"
]
},
{
"id": "770713272",
"name": "James Anthony Cotton",
"characters": []
}
],
"links": {
"rel": "http://api.rottentomatoes.com/api/public/v1.0/movies/770672122.json"
}
}
I'm just trying to get this code to work but I'm getting an InvalidOperationException and this error
"Type 'System.String' is not supported for deserialization of an array."
Here's my code in main
string json = File.ReadAllText("json.txt");
CastInfo castMember = new JavaScriptSerializer().Deserialize<CastInfo>(json);
Here are my classes
public class CastInfo
{
public List<CustomCastInfo> cast { get; set; }
}
public class CustomCastInfo
{
public string id { get; set; }
public string name { get; set; }
public List<string> characters { get; set; }
}
And advice? And I realize I need to do something about the "links" in the bottom, but even when I delete that it still doesn't work.
I just tried running this with the json you provided and it worked fine.
using System.Collections.Generic;
using System.IO;
using System.Web.Script.Serialization;
namespace JsonDeserialization
{
class Program
{
static void Main(string[] args)
{
string json = File.ReadAllText("json.txt");
CastInfo castMember = new JavaScriptSerializer().Deserialize<CastInfo>(json);
}
}
public class CastInfo
{
public List<CustomCastInfo> cast { get; set; }
}
public class CustomCastInfo
{
public string id { get; set; }
public string name { get; set; }
public List<string> characters { get; set; }
}
}
Related
I am trying to resolve the some complex JSON I am receiving to convert it to a C# Model so I can analyse and manipulate the data. I have tried converting the JSON by using JSON to C# but it doesn't work well when the name is dynamic. I want to focus on the Data.
The Item1 and SubItem1 etc are all variable strings so I can't hard code a model to pull them and the text is just a string within. The issue I am having is how to get the JSON into a usable format to access the Item1, SubItem1 and text values to manipulate their data.
I have looked into Dictionaries as suggested elsewhere but I am having no luck.
Model I have tried
public class Data
{
public string Status { get; set; }
public ResultInfo ResultInfo { get; set; }
public string Message { get; set; }
public Dictionary<string, SubData> Data {get;set;}
}
public class SubData
{
public Dictionary<string,List<string>> item {get;set;}
}
JSON
{
"Status": "OK",
"ResultInfo": {
"Prev": "PageUPURL",
"Next": "PageDownURL",
"total_count": "37",
"per_page": "3",
"page": "1"
},
"Message": "Ok.",
"Data": {
"Item1": [
{
"SubItem1": [
"Text"
]
}
],
"Item2": [
{
"SubItem2": [
"Text",
"Text",
"Text"
]
}
],
"Item3": [
{
"SubItem3": [
"Text"
]
},
{
"SubItem4": [
"Text"
]
}
]
}
}
Any suggestions, advice or help would be gratefully received.
For those task I use https://app.quicktype.io .
Because it can easly reconnize dictionary when the property name are numeric you just need to edit your Json a little.
And past it into the tool.
{
"Status": "OK",
"ResultInfo": {
"Prev": "PageUPURL",
"Next": "PageDownURL",
"total_count": "37",
"per_page": "3",
"page": "1"
},
"Message": "Ok.",
"Data": {
"1": [
{
"1": [
"Text"
]
}
],
"2": [
{
"1": [
"Text",
"Text",
"Text"
]
}
],
"3": [
{
"1": [
"Text"
]
},
{
"2": [
"Text"
]
}
]
}
}
The result class is :
public partial class Root
{
[JsonProperty("Status")]
public string Status { get; set; }
[JsonProperty("ResultInfo")]
public ResultInfo ResultInfo { get; set; }
[JsonProperty("Message")]
public string Message { get; set; }
[JsonProperty("Data")]
public Dictionary<string, List<Dictionary<string, List<string>>>> Data { get; set; }
}
public partial class ResultInfo
{
[JsonProperty("Prev")]
public string Prev { get; set; }
[JsonProperty("Next")]
public string Next { get; set; }
[JsonProperty("total_count")]
[JsonConverter(typeof(ParseStringConverter))]
public long TotalCount { get; set; }
[JsonProperty("per_page")]
[JsonConverter(typeof(ParseStringConverter))]
public long PerPage { get; set; }
[JsonProperty("page")]
[JsonConverter(typeof(ParseStringConverter))]
public long Page { get; set; }
}
Online Demo https://dotnetfiddle.net/1j42kR
nota bene: that tool also included a converter from "string" to "long" for "per_page": "3",
Change below line
public Dictionary<string, SubData> Data {get;set;}
as
public Dictionary<string, Dictionary<string, string[]>[]> Data { get; set; }
I'm using Json.NET to deserialize incoming json data into an object, but I want to flatten one of the a nested data into a property as an array.
What my incoming json data looks like:
{
“sets": {
"set": [
{
"name": "Act 1:",
“title”: [
{
"name": “A”
},
{
"name": “B”
},
{
"name": “C”
},
{
"name": “D”
}
]
},
{
"name": "Act 2:",
“title”: [
{
"name": “E”
},
{
"name": “F”
},
{
"name": “G”
}
]
}
]
}
}
What I want the transformed data to look like when object is serialized:
{
“sets": {
“title”: [
{
"name": “A”
},
{
"name": “B”
},
{
"name": “C”
},
{
"name": “D”
},
{
"name": “E”
},
{
"name": “F”
},
{
"name": “G”
}
]
}
}
What approach can I take to achieve this? Is it possible to customize how my object gets deserialized?
I know you are asking for it to be done in the deserialization but this gives the same results.
https://dotnetfiddle.net/U89KwW
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
public class Program
{
public const string Json = "{\"sets\": {\"set\": [{\"name\": \"Act 1:\",\"title\": [{\"name\":\"A\"},{\"name\": \"B\"},{\"name\": \"C\"},{\"name\": \"D\"}]},{\"name\": \"Act 2:\",\"title\": [{\"name\": \"E\"},{\"name\": \"F\"},{\"name\": \"G\"}]}]}}";
public static void Main()
{
Something something = JsonConvert.DeserializeObject<Something>(Json);
something.Titles = something.sets.set.SelectMany(c=> c.title).ToList();
something.sets = null;
string JsonResult = JsonConvert.SerializeObject(something);
Console.WriteLine(JsonResult);
}
}
public class Something
{
public Sets sets {get;set;}
public List<Title> Titles {get;set;}
}
public class Sets
{
public List<Set> set {get;set;}
}
public class Set
{
public string name {get;set;}
public List<Title> title {get;set;}
}
public class Title
{
public string name {get;set;}
}
I want to deserialize this json to a List of Product objects but i get this error:
Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[ShoppingList.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.
This is my code:
{
"records": [
{
"id": "60",
"name": "Rolex Watch",
"description": "Luxury watch.",
"price": "25000",
"category_id": "1",
"category_name": "Fashion"
},
{
"id": "48",
"name": "Bristol Shoes",
"description": "Awesome shoes.",
"price": "999",
"category_id": "5",
"category_name": "Movies"
},
{
"id": "42",
"name": "Nike Shoes for Men",
"description": "Nike Shoes",
"price": "12999",
"category_id": "3",
"category_name": "Motors"
}
]
}
public class Product
{
public int id { get; set; }
public string name { get; set; }
public string description { get; set; }
public decimal price { get; set; }
public int category_id { get; set; }
public string category_name { get; set; }
}
public async Task<List<Product>> GetProductsAsync()
{
Products = new List<Product>();
var uri = new Uri("https://hostname/api/product/read.php");
try
{
var response = await client.GetAsync(uri);
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
Products = JsonConvert.DeserializeObject<List<Product>>(content);
}
}
catch (Exception )
{
throw;
}
return Products;
}
Your Json is not a List<Product>, its an object with a single property called records which is a List<Product>.
So your actual C# model is this:
public class RootObject
{
public List<Product> records { get; set; }
}
And you deserialize like this:
RootObject productsRoot = JsonConvert.DeserializeObject<RootObject>(content);
The issue is that your response JSON you've provided is an object which contains a list, but you are trying to deserialize the data into a straight list. I think all you need to do is add a second class which contains the list into your code, then deserialize using that list.
public class Product
{
public int id { get; set; }
public string name { get; set; }
public string description { get; set; }
public decimal price { get; set; }
public int category_id { get; set; }
public string category_name { get; set; }
}
public class RootProduct
{
public List<Product> Products {get;set;}
}
Then you change your deserialization portion from List to
RootProduct response = JsonConvert.DeserializeObject<RootProduct>(content);
The usage would then simply be products. response.Products to access the list of items.
The problem is your json structure. Below is an example of a json array - notice i removed the property "records".
[
{
"id": "60",
"name": "Rolex Watch",
"description": "Luxury watch.",
"price": "25000",
"category_id": "1",
"category_name": "Fashion"
},
{
"id": "48",
"name": "Bristol Shoes",
"description": "Awesome shoes.",
"price": "999",
"category_id": "5",
"category_name": "Movies"
},
{
"id": "42",
"name": "Nike Shoes for Men",
"description": "Nike Shoes",
"price": "12999",
"category_id": "3",
"category_name": "Motors"
}
]
Given this data
[
{
"id": "60",
"name": "Rolex Watch",
"description": "Luxury watch.",
"price": "25000",
"category_id": "1",
"category_name": "Fashion"
},
{
"id": "48",
"name": "Bristol Shoes",
"description": "Awesome shoes.",
"price": "999",
"category_id": "5",
"category_name": "Movies"
},
{
"id": "42",
"name": "Nike Shoes for Men",
"description": "Nike Shoes",
"price": "12999",
"category_id": "3",
"category_name": "Motors"
}
]
And this class definition
public class Order
{
public int id { get; set; }
public string name { get; set; }
public string description { get; set; }
public string price { get; set; }
public string category_id { get; set; }
public string category_name { get; set; }
}
The code to convert it from JSON to a C# List<Order> is:
public static List<Order> Map(string json)
{
return Newtonsoft.Json.JsonConvert.DeserializeObject<List<Order>>(json);
}
First: I'm new to using JSON, and I used the answers on here to use Json.Net to deserialize data from a Pokemon API into a C# class (Pokemon class). I used http://json2csharp.com to help me define my class and it looks like this:
public class Pokemon
{
public Pokemon(string json)
{
JsonConvert.PopulateObject(json, this, PokeApi.JsonSerializerSettings);
}
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("evolutions")]
public Evolutions evolutions { get; set; }
[JsonProperty("national_id")]
public int national_id { get; set; }
}
with a bunch of other properties like resource_uri, attack stat, etc.
As the answer offered on the aforementioned link said, I used JsonConvert.DeserializeObject(json) like so:
public Pokemon GetPokemon(int nationalId)
{
using (WebClient client = new WebClient())
{
var json = client.DownloadString("http://pokeapi.co/api/v1/pokemon/" + nationalId + "/");
var output = JsonConvert.DeserializeObject<Pokemon>(json);
return output;
}
}
However I keep getting an exception that says "Cannot deserialize the current JSON array (e.g.[1,2,3]) into type 'Evolutions' because the type requires a JSON object..."
I found a lot of other questions asking the same exact thing, but I was confused with the top answers - sometimes the answer was to use JsonProperty, sometimes it was to use JsonConverter, without really an explanation on what all these meant. Do I need both?
Edit: sample json (call: http://pokeapi.co/api/v1/pokemon/1/)
{
"abilities": [
{
"name": "overgrow",
"resource_uri": "/api/v1/ability/1/"
},
{
"name": "chlorophyll",
"resource_uri": "/api/v1/ability/2/"
}
],
"attack": 49,
"catch_rate": 45,
"created": "2013-11-02T12:08:25.745455",
"defense": 49,
"egg_cycles": 21,
"egg_groups": [
{
"name": "Monster",
"resource_uri": "/api/v1/egg/1/"
},
{
"name": "Grass",
"resource_uri": "/api/v1/egg/8/"
}
],
"ev_yield": "1 Sp Atk",
"evolutions": {
"level": 16,
"method": "level up",
"resource_uri": "/api/v1/pokemon/2/",
"to": "Ivysaur"
},
"exp": 64,
"growth_rate": "ms",
"happiness": 70,
"height": "2'4",
"hp": 45,
"male_female_ratio": "87.5/12.5",
"modified": "2013-11-02T13:28:04.914889",
"moves": [
{
"learn_type": "other",
"name": "Tackle",
"resource_uri": "/api/v1/move/1/"
},
{
"learn_type": "other",
"name": "Growl",
"resource_uri": "/api/v1/move/2/"
},
{
"learn_type": "level up",
"level": 10,
"name": "Vine whip",
"resource_uri": "/api/v1/move/3/"
}
],
"name": "Bulbasaur",
"national_id": 1,
"resource_uri": "/api/v1/pokemon/4/",
"sp_atk": 65,
"sp_def": 65,
"species": "seed pokemon",
"speed": 45,
"total": 318,
"types": [
{
"name": "grass",
"resource_uri": "/api/v1/type/5/"
},
{
"name": "poison",
"resource_uri": "/api/v1/type/8/"
}
],
"weight": "15.2lbs"
}
Evolutions class:
public class Evolutions
{
public int level { get; set; }
public string method { get; set; }
public string resource_uri { get; set; }
public string to { get; set; }
}
I tried http://json2csharp.com/ with http://pokeapi.co/api/v1/pokemon/19/ and what I see is
public class RootObject
{
//...
public List<Evolution> evolutions { get; set; }
//...
}
This pretty mush is your Pokemon class. So you need to declare Evolutions as list.
I'm trying to deserialize a json string and I'm getting the error End element 'caption' from namespace '' expected. Found element 'created_time' from namespace ''. when calling
InstagramObject test = (InstagramObject) instagramObject.ReadObject(instagramWebResponse.GetResponseStream());
The json from Instagram returns many elements but there are only a few that I need. My DataContract will be posted below.
Basically I need {data:[{caption: string, link: string, images: {...}}]}
Here's an example of the json...
{
"data": [{
"comments": {
"data": [],
"count": 0
},
"caption": {
"created_time": "1296710352",
"text": "Inside le truc #foodtruck",
"from": {
"username": "kevin",
"full_name": "Kevin Systrom",
"type": "user",
"id": "3"
},
"id": "26621408"
},
"likes": {
"count": 15,
"data": [{
"username": "mikeyk",
"full_name": "Mike Krieger",
"id": "4",
"profile_picture": "..."
}, {...subset of likers...}]
},
"link": "http://instagr.am/p/BWrVZ/",
"user": {
"username": "kevin",
"profile_picture": "http://distillery.s3.amazonaws.com/profiles/profile_3_75sq_1295574122.jpg",
"id": "3"
},
"created_time": "1296710327",
"images": {
"low_resolution": {
"url": "http://distillery.s3.amazonaws.com/media/2011/02/02/6ea7baea55774c5e81e7e3e1f6e791a7_6.jpg",
"width": 306,
"height": 306
},
"thumbnail": {
"url": "http://distillery.s3.amazonaws.com/media/2011/02/02/6ea7baea55774c5e81e7e3e1f6e791a7_5.jpg",
"width": 150,
"height": 150
},
"standard_resolution": {
"url": "http://distillery.s3.amazonaws.com/media/2011/02/02/6ea7baea55774c5e81e7e3e1f6e791a7_7.jpg",
"width": 612,
"height": 612
}
},
"type": "image",
"filter": "Earlybird",
"tags": ["foodtruck"],
"id": "22721881",
"location": {
"latitude": 37.778720183610183,
"longitude": -122.3962783813477,
"id": "520640",
"street_address": "",
"name": "Le Truc"
}
}]
}
and here's my DataContract...
[DataContract]
public class InstagramObject {
[DataMember(Name = "data")]
public IEnumerable<InstagramData> instagramData { get; set; }
}
[DataContract]
public class InstagramData {
[DataMember(Name = "images")]
public List<InstagramImage> instagramImages { get; set; }
[DataMember(Name = "caption")]
public string caption { get; set; }
[DataMember(Name = "link")]
public string link { get; set; }
}
[DataContract]
public class InstagramImage {
[DataMember(Name = "low_resolution")]
public InstagramImageInfo lowResolutionImage { get; set; }
[DataMember(Name = "thumbnail")]
public InstagramImageInfo thumbnail { get; set; }
[DataMember(Name = "standard_resolution")]
public InstagramImageInfo standardResolution { get; set; }
}
[DataContract]
public class InstagramImageInfo {
[DataMember(Name = "url")]
public string url { get; set; }
[DataMember(Name = "width")]
public int width { get; set; }
[DataMember(Name = "height")]
public int height { get; set; }
}
In the data contract caption is declared as a string, but in the JSON caption is a record with various fields - caption should be declared to be an object with a compatible structure:
[DataContract]
public class InstagramCaption {
[DataMember(Name = "text")]
public string Text {get; set;}
}
. . .
[DataMember(Name = "caption")]
public InstagramCaption caption { get; set; }
. . .
No need to declare those clases If you want to go with Json.Net + Linq
var obj = (JObject)JsonConvert.DeserializeObject(json);
var result = obj["data"]
.Select(x => new {
Caption = (string)x["caption"]["text"],
Link = (string)x["link"],
Images = x["images"].Children()
.Select(y=>(string)y.First()["url"]).ToArray()
})
.ToArray();