Json deserialization with different variable names (FIXED Posted Solution) - c#

Hello I'm working on a windows form application to enter in Magic The Gathering cards I have into a database for easy organization. In order to enter the card data fast I plan on using the MTG master card Json file which contains every card made and all of it's attributes. But the way they have the Json file doesn't seem to work well with the deserialization in Visual C#.
Here is what two entries look like:
{
"Air Elemental":{
(stuff that doesn't matter for the question)
},
"Ancestral Recall":{
. . .
}
}
As you can see the variable name for the data is different for every single one which is where the problem lies. I can't get C# to deserialize it correctly into a class because it wants the JsonProperty name and because it is different I can't really set it.
So if there is a way to specify that it doesn't need to have a specific name and it just stores what's placed in that variable I would really appreciate if you could tell me.
Thank you for any help you can provide.
SOLUTION
Thanks to Henrik I found out how to fix this problem. Here is what he posted:
dynamic data = JsonConvert.DeserializeObject(responseData);
IDictionary<string, JToken> cards = data;
foreach (var card in cards)
{
var key = card.Key;
var value = card.Value;
}
Which wasn't fully what I had to do but it laid out the ground of the solution. I figured out that the card.Value actually held all the Json text of the card so all I needed to do was use Json.DeserializeObject one more time but this time into my class that has all the values set to variables. Here's what it looks like
string json;
using (StreamReader sr = new StreamReader("G:/MTG Card Database/Files/AllCardsShort.json"))
{
json = sr.ReadToEnd();
sr.Close();
}
dynamic data = JsonConvert.DeserializeObject(json);
IDictionary<string, JToken> cards = data;
foreach (var card in cards)
{
CardData newCard = JsonConvert.DeserializeObject<CardData>(card.Value.ToString());
textBox1.Text = newCard.name; //Check to see if the name can be put into a textbox
break;
}
. . .
public class CardData
{
[JsonProperty("layout")]
public string layout { get; set; }
[JsonProperty("name")]
public string name { get; set; }
[JsonProperty("manaCost")]
public string manaCost { get; set; }
[JsonProperty("cmc")]
public string cmc { get; set; }
[JsonProperty("colors")]
public string[] colors { get; set; }
[JsonProperty("type")]
public string type { get; set; }
[JsonProperty("subtypes")]
public string[] subTypes { get; set; }
[JsonProperty("text")]
public string text { get; set; }
[JsonProperty("power")]
public string power { get; set; }
[JsonProperty("toughness")]
public string toughness { get; set; }
[JsonProperty("imageName")]
public string imageName { get; set; }
}
So again thank you Henrik for helping out. And thank you to everyone else that posted their idea as well!

Using Json.NET:
dynamic data = JsonConvert.DeserializeObject(responseData);
IDictionary<string, JToken> cards = data;
foreach (var card in cards)
{
var key = card.Key;
var value = card.Value;
}

Could this be what you are looking for? Check Tom Peplow's answer here
Deserialize JSON into C# dynamic object?
dynamic stuff = JsonConvert.DeserializeObject("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");
string name = stuff.Name;
string address = stuff.Address.City;

Related

Get multiples Arrays from dictionary Object

I have a JSON call, this brings me an object with four Arrays.
HttpWebRequest apiRequest = WebRequest.Create(url) as HttpWebRequest;
string apiResponse = "";
using (HttpWebResponse response = apiRequest.GetResponse() as HttpWebResponse)
{
StreamReader reader = new StreamReader(response.GetResponseStream());
apiResponse = reader.ReadToEnd();
}
var dict = new JavaScriptSerializer().Deserialize<Dictionary<string, object>>(apiResponse);
var results = dict["results"];
Then i use var dict to storage this four arrays, later i have var results to select an specific array. In this case, the array i want is "results".
var results "output":
The problem is i want access the data for each array, but i don't know how do this.
ArrayList list = (ArrayList)results;
StringBuilder builder = new StringBuilder();
for (int i = 0; i < list.Count; i++)
{
if (builder.Length > 0)
{
builder.Append(", ");
}
object current = list[i];
builder.Append(current);
}
LblTitle.Text = builder.ToString();
I see this code in other post and i adapt to my code, but this only brings me this System.Collections.Generic.Dictionary'2[System.String,System.Object], for each array.
I want something like this
string[] arrayresult = builder.ToString();
string[] arrayresult2 = builder.ToString();
etc, for each array in the object results. And later access each array data like this LblTitle.Text = arrayresult[1]; LblTitle2.Text = arrayresult2[1];
Edit: Adding JSON Example
"{\"page\":1,\"results\":[{\"adult\":false,\"backdrop_path\":\"/7ABsaBkO1jA2psC8Hy4IDhkID4h.jpg\",\"genre_ids\":[28,12,14,878],\"id\":19995,\"original_language\":\"en\",\"original_title\":\"Avatar\",\"overview\":\"In the 22nd century, a paraplegic Marine is dispatched to the moon Pandora on a unique mission, but becomes torn between following orders and protecting an alien civilization.\",\"popularity\":1363.938,\"poster_path\":\"/jRXYjXNq0Cs2TcJjLkki24MLp7u.jpg\",\"release_date\":\"2009-12-10\",\"title\":\"Avatar\",\"video\":false,\"vote_average\":7.5,\"vote_count\":26216},{\"adult\":false,\"backdrop_path\":\"/198vrF8k7mfQ4FjDJsBmdQcaiyq.jpg\",\"genre_ids\":[878,28,12],\"id\":76600,\"original_language\":\"en\",\"original_title\":\"Avatar: The Way of Water\",\"overview\":\"Set more than a decade after the events of the first film, learn the story of the Sully family (Jake, Neytiri, and their kids), the trouble that follows them, the lengths they go to keep each other safe, the battles they fight to stay alive, and the tragedies they endure.\",\"popularity\":1000.602,\"poster_path\":\"/1yppMeTNQwDrzaUH4dRCx4mr8We.jpg\",\"release_date\":\"2022-12-14\",\"title\":\"Avatar: The Way of Water\",\"video\":false,\"vote_average\":0,\"vote_count\":0},{\"adult\":false,\"backdrop_path\":null,\"genre_ids\":[99],\"id\":287003,\"original_language\":\"en\",\"original_title\":\"Avatar: Scene Deconstruction\",\"overview\":\"The deconstruction of the Avatar scenes and sets\",\"popularity\":261.979,\"poster_path\":\"/uCreCQFReeF0RiIXkQypRYHwikx.jpg\",\"release_date\":\"2009-12-18\",\"title\":\"Avatar: Scene Deconstruction\",\"video\":false,\"vote_average\":9,\"vote_count\":3},{\"adult\":false,\"backdrop_path\":null,\"genre_ids\":[99],\"id\":111332,\"original_language\":\"en\",\"original_title\":\"Avatar: Creating the World of Pandora\",\"overview\":\"The Making-of James Cameron's Avatar. It shows interesting parts of the work on the set.\",\"popularity\":259.613,\"poster_path\":\"/d9oqcfeCyc3zmMal6eJbfj3gatc.jpg\",\"release_date\":\"2010-02-07\",\"title\":\"Avatar: Creating the World of Pandora\",\"video\":false,\"vote_average\":7,\"vote_count\":20}],\"total_pages\":3,\"total_results\":55}"
I convert this JSON to Class, thanks for the tip. This is my class now:
public class Result
{
public bool adult { get; set; }
public string backdrop_path { get; set; }
public List<int> genre_ids { get; set; }
public int id { get; set; }
public string original_language { get; set; }
public string original_title { get; set; }
public string overview { get; set; }
public double popularity { get; set; }
public string poster_path { get; set; }
public string release_date { get; set; }
public string title { get; set; }
public bool video { get; set; }
public double vote_average { get; set; }
public int vote_count { get; set; }
}
public class Root
{
public int page { get; set; }
public List<Result> results { get; set; }
public int total_pages { get; set; }
public int total_results { get; set; }
}
I would suggest you create a proper C# class to deserialize your JSON into. We can't see how you JSON looks, so I'll just give a simple example. Let's say this is your JSON:
{
"results": [
[
"foo",
"bar"
],
[
"baz",
"qux"
]
],
"someOtherField": "someValue"
}
If you go to https://json2csharp.com/ you can convert this into a C# class like this:
public class Root
{
public List<List<string>> results { get; set; }
public string someOtherField { get; set; }
}
To deserialize and access the data, you simply do the following (I'm using System.Text.Json instead of JavaScriptSerializer - see comment below):
var root = JsonSerializer.Deserialize<Root>(apiResponse);
// ...
List<string> listResult = root.results[0];
List<string> listResult2 = root.results[1];
// ...
LblTitle.Text = listResult[1]; // "bar"
LblTitle2.Text = listResult2[1]; // "qux"
Please refer to the definition of JavaScriptSerializer:
For .NET Framework 4.7.2 and later versions, use the APIs in the System.Text.Json namespace for serialization and deserialization. For earlier versions of .NET Framework, use Newtonsoft.Json.
See here for how to use System.Text.Json .
If you want to use Newtonsoft.Json instead, you should replace JsonSerializer.Deserialize with JsonConvert.DeserializeObject:
var root = JsonConvert.DeserializeObject<Root>(apiResponse);

Looping through a Json array (C#)

I have been working on some automated tests with selenium and I need to get some data out of a JSON file.
how can i go about coding this, i have this so far
string json = File.ReadAllText("myfilepath");
dynamic data = jsonConvert.DeserializeObject(json);
string x = data[0].CountryName.Value;
foreach(var CN in data.countryName)
{
var CountryName = CN.CountryName;
}
I am a bit stuck on getting data through to loop it
Any help would be amazing guys
Example Json :
[
{
"CountryLookupId":123,
"CountryName":data,
"CountryLocation": moredata
}
]
I am trying to loop through the CountryName,i need to loop through 31 things
With out testing it. make a object model:
public class CountryClass
{
[JsonProperty("CountryLookupId")]
[JsonConverter(typeof(ParseStringConverter))]
public long CountryLookupId { get; set; }
[JsonProperty("CountryName")]
public string CountryName { get; set; }
[JsonProperty("CountryLocation")]
public string CountryLocation { get; set; }
}
Than deserialize list of object model:
List<CountryClass> data = jsonConvert.DeserializeObject<List<CountryClass>>(json);
Finally you can loop over your list of country objects:
foreach(var cn in data)
{
var countryName = cn.CountryName;
}

How can I get values from a complex Json object?

I am trying to get values from Json objects that all are formed like this one:
http://services.runescape.com/m=itemdb_rs/api/catalogue/detail.json?item=4798
I tried several libraries but none of them resulted in the way I wanted. I want to put the values into specific Datamembers.
This was my last attempt, it runs but it seems like my Datamembers are not getting any values.
namespace JSON_Data
{
public partial class Form1 : Form
public Form1()
{
InitializeComponent();
string jsonString = #"{""item"":{""icon"":""http://services.runescape.com/m=itemdb_rs/4996_obj_sprite.gif?id=4798"",""icon_large"":""http://services.runescape.com/m=itemdb_rs/4996_obj_big.gif?id=4798"",""id"":4798,""type"":""Ammo"",""typeIcon"":""http://www.runescape.com/img/categories/Ammo"",""name"":""Adamant brutal"",""description"":""Blunt adamantite arrow...ouch"",""current"":{""trend"":""neutral"",""price"":305},""today"":{""trend"":""neutral"",""price"":0},""members"":""true"",""day30"":{""trend"":""positive"",""change"":""+2.0%""},""day90"":{""trend"":""positive"",""change"":""+8.0%""},""day180"":{""trend"":""positive"",""change"":""+23.0%""}}}";
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Item));
MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(jsonString));
Item obj = (Item)ser.ReadObject(stream);
}
}
}
This is how my class "Item" looks
namespace JSON_Data
{
[DataContract]
public class Item
{
[DataMember]
public string Icon { get; set; }
[DataMember]
public string Icon_large { get; set; }
[DataMember]
public int Id { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public string Description { get; set; }
[DataMember]
public string Members { get; set; }
}
}
if you can try the Newtonsoft i can provide a way.. its very good and better approach as far as i think
var ob = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(jsonString);
Item a = ((JObject)ob["item"]).ToObject<Item>();
There are several JSON serializers you can use in C#. Some have better performance, some have better fault tolerance and others have circular reference treatments.
In your case, I see that you simply want an object without passing it (to a WCF) anywhere. You can follow the second answer of this question: Deserialize JSON into C# dynamic object? Example code copied from that answer:
dynamic stuff = JsonConvert.DeserializeObject("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");
string name = stuff.Name;
string address = stuff.Address.City;
A dynamic object in C# allows you to read a property without declaring a class for it.

System.ArgumentException: invalid JSON primitive:. but only when browsing from mobile browser

I have a simple test responsive aspx web page, that download json data and try to display results.
If i browse from the desktop/laptop computer i do not receive any error everything is ok, json data are deserialized and data are shown (i can list results about students) but if i open via mobile browser i receive System.ArgumentException: invalid JSON primitive:.
I dont know what can be the reason,or where to search the problem since in one case is working as espected
Json string is like this and is very simple:
{
"students":[
{
"studentName":"TEST- MORE TEST",
"MoreInfo":"sdpThP5YUMsaFfwOM7tj",
"Counter":"404",
"Age":"20"
}
]
}
I try to replace all dots in strings, remove all special characters and without results, i remove all records and only with one still dont work i cant figure out what can be wrong:
c# code that i use for desalinize:
using (var wc = new System.Net.WebClient())
{
//here i download my json data
string json = wc.DownloadString(download_url);
JavaScriptSerializer jss = new JavaScriptSerializer();
var myStudents = jss.Deserialize<studentList>(json);
foreach (student student in myStudents.students)
{
Response.Write(student.studentName + " " + student.Age </br>");
}
}
any help appreciated, thanks
Here is how is model defined:
public class student
{
public string studentName { get; set; }
public string MoreInfo { get; set; }
public string Counter { get; set; }
public string Age { get; set; }
}
public class studentList
{
public List<student> students { get; set; }
}

Parsing Json facebook c#

I am trying for many hours to parse a JsonArray, I have got by graph.facebook, so that i can extra values. The values I want to extract are message and ID.
Getting the JasonArry is no Problem and works fine:
[
{
"code":200,
"headers":[{"name":"Access-Control-Allow-Origin","value":"*"}],
"body":"{
\"id\":\"255572697884115_1\",
\"from\":{
\"name\":\"xyzk\",
\"id\":\"59788447049\"},
\"message\":\"This is the first message\",
\"created_time\":\"2011-11-04T21:32:50+0000\"}"},
{
"code":200,
"headers":[{"name":"Access-Control-Allow-Origin","value":"*"}],
"body":"{
\"id\":\"255572697884115_2\",
\"from\":{
\"name\":\"xyzk\",
\"id\":\"59788447049\"},
\"message\":\"This is the second message\",
\"created_time\":\"2012-01-03T21:05:59+0000\"}"}
]
Now I have tried several methods to get access to message, but every method ends in catch... and throws an exception.
For example:
var serializer = new JavaScriptSerializer();
var result = serializer.Deserialize<dynamic>(json);
foreach (var item in result)
{
Console.WriteLine(item.body.message);
}
throws the exception: System.Collections.Generic.Dictionary doesnt contain definitions for body. Nevertheless you see in the screenshot below, that body contains definitions.
Becaus I am not allowed to post pictures you can find it on directupload: http://s7.directupload.net/images/120907/zh5xyy2k.png
I don't havent more ideas so i please you to help me. I need this for a project, private, not commercial.
Maybe you could give me an phrase of code, so i can continue my development.
Thank you so far
Dominic
If you use Json.Net, All you have to do is
replacing
var serializer = new JavaScriptSerializer();
var result = serializer.Deserialize<dynamic>(json);
with
dynamic result = JsonConvert.DeserializeObject(json);
that's all.
You are not deserializing to a strongly typed object so it's normal that the applications throws an exception. In other words, the deserializer won't create an Anynymous class for you.
Your string is actually deserialized to 2 objects, each containing Dictionary<string,object> elements. So what you need to do is this:
var serializer = new JavaScriptSerializer();
var result = serializer.Deserialize<dynamic>(s);
foreach(var item in result)
{
Console.WriteLine(item["body"]["message"]);
}
Here's a complete sample code:
void Main()
{
string json = #"[
{
""code"":200,
""headers"":[{""name"":""Access-Control-Allow-Origin"",""value"":""*""}],
""body"":{
""id"":""255572697884115_1"",
""from"":{
""name"":""xyzk"",
""id"":""59788447049""},
""message"":""This is the first message"",
""created_time"":""2011-11-04T21:32:50+0000""}},
{
""code"":200,
""headers"":[{""name"":""Access-Control-Allow-Origin"",""value"":""*""}],
""body"":{
""id"":""255572697884115_2"",
""from"":{
""name"":""xyzk"",
""id"":""59788447049""},
""message"":""This is the second message"",
""created_time"":""2012-01-03T21:05:59+0000""}}
]";
var serializer = new JavaScriptSerializer();
var result = serializer.Deserialize<dynamic>(json);
foreach(var item in result)
{
Console.WriteLine(item["body"]["message"]);
}
}
Prints:
This is the first message
This is the second message
I am using this simple technique
var responseTextFacebook =
#"{
"id":"100000891948867",
"name":"Nishant Sharma",
"first_name":"Nishant",
"last_name":"Sharma",
"link":"https:\/\/www.facebook.com\/profile.php?id=100000891948867",
"gender":"male",
"email":"nihantanu2010\u0040gmail.com",
"timezone":5.5,
"locale":"en_US",
"verified":true,
"updated_time":"2013-06-10T07:56:39+0000"
}"
I have declared a class
public class RootObject
{
public string id { get; set; }
public string name { get; set; }
public string first_name { get; set; }
public string last_name { get; set; }
public string link { get; set; }
public string gender { get; set; }
public string email { get; set; }
public double timezone { get; set; }
public string locale { get; set; }
public bool verified { get; set; }
public string updated_time { get; set; }
}
Now I am deserializing
JavaScriptSerializer objJavaScriptSerializer = new JavaScriptSerializer();
RootObject parsedData = objJavaScriptSerializer.Deserialize<RootObject>(responseTextFacebook );

Categories

Resources