I want to collect the information of this Json:
{"name":"Maltarya","race":"Sylvari","gender":"Female","profession":"Thief","level":80,"equipment":[{"id":4483,"slot":"HelmAquatic","upgrades":[24723]},{"id":59,"slot":"Backpack","upgrades":[24498],"skin":2381},{"id":11805,"slot":"Coat","upgrades":[24815]},{"id":11889,"slot":"Boots","upgrades":[24723]},{"id":11847,"slot":"Gloves","upgrades":[24815]},{"id":11973,"slot":"Helm","upgrades":[24815]},{"id":11763,"slot":"Leggings","upgrades":[24815]},{"id":11931,"slot":"Shoulders","upgrades":[24815]},{"id":39141,"slot":"Accessory1","upgrades":[24545]}]}
But i have an error when i want to collect the equipment informations.
My code is:
WebRequest request = WebRequest.Create("https://api.guildwars2.com/v2/characters/" + name + "?access_token=" + key);
var response = (HttpWebResponse)request.GetResponse();
var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
Personnages perso = JsonConvert.DeserializeObject<Personnages>(responseString);
and my Personnages class:
class Personnages
{
public string name { get; set; }
public string race { get; set; }
public string gender { get; set; }
public string profession { get; set; }
public string level { get; set; }
public IList<string> equipment { get; set; }
}
The exception i have is: Unexpected token: Error reading string. StartObject.
You are trying to deserialize JSON array to a IList<string>. However, this array contains objects, but not strings.
You need to implement another one class for these objects and use it in deserialization:
class EquipmentItem
{
public int id { get; set; }
public string slot { get; set; }
public List<int> upgrades { get; set; }
}
class Personnages
{
public string name { get; set; }
public string race { get; set; }
public string gender { get; set; }
public string profession { get; set; }
public string level { get; set; }
public List<EquipmentItem> equipment { get; set; }
}
Personnages perso = JsonConvert.DeserializeObject<Personnages>(responseString);
Related
I am trying to deserialize my json code. The json code is in a string, and the json code looks like this (so I'm assuming it's json objects)
{
"post_id":13,
"thread_id":9,
"user_id":1,
"username":"Username",
"post_date":1496439611,
"message":"testzilla - 2133746943A9",
"ip_id":698,
"message_state":"visible",
"attach_count":0,
"position":0,
"likes":0,
"like_users":"a:0:{}",
"warning_id":0,
"warning_message":"",
"last_edit_date":1496476199,
"last_edit_user_id":0,
"edit_count":9,
"node_id":34,
"title":"Test",
"tags":"a:0:{}",
"node_title":"test node",
"node_name":null,
"message_html":"testzilla - 2133746943A9",
"absolute_url":"url"
}
How would I put the "message" container inside a string? So that the string would contain "testzilla - 2133746943A9" without the quotation marks. I am using JSON.Net
The name of the string that contains this json code is "MACs". Thanks in advance. PS: I am a new coder.
there is a missing "{" at the beginning of your json file, try adding it
You need to create your c# class to deserialize your json string. As per your json structure i have created your class given below
public class MyClass
{
public int post_id { get; set; }
public int thread_id { get; set; }
public int user_id { get; set; }
public string username { get; set; }
public int post_date { get; set; }
public string message { get; set; }
public int ip_id { get; set; }
public string message_state { get; set; }
public int attach_count { get; set; }
public int position { get; set; }
public int likes { get; set; }
public string like_users { get; set; }
public int warning_id { get; set; }
public string warning_message { get; set; }
public int last_edit_date { get; set; }
public int last_edit_user_id { get; set; }
public int edit_count { get; set; }
public int node_id { get; set; }
public string title { get; set; }
public string tags { get; set; }
public string node_title { get; set; }
public object node_name { get; set; }
public string message_html { get; set; }
public string absolute_url { get; set; }
}
No need to use library JSON.Net. You can do this by simply using System.Web.Script.Serialization to deserialize the json string.
Note : System.Web.Script.Serialization is available inside System.Web.Extensions namespace.
Below is the complete code. I kept your json data inside a file named as "test2.json" and consuming it from that file.
using System;
using System.Web.Script.Serialization;
using System.IO;
namespace DesrializeJson1ConsoleApp
{
class Program
{
static void Main(string[] args)
{
var jsonFile = "test2.json";
string jsonstring = File.ReadAllText(jsonFile);
var serializer = new JavaScriptSerializer();
MyClass aClass = serializer.Deserialize<MyClass>(jsonstring);
Console.WriteLine("--------------------------");
Console.WriteLine("message :" + aClass.message);
Console.WriteLine("message_state :" + aClass.message_state);
Console.WriteLine("warning_message :" + aClass.warning_message);
Console.WriteLine("message_html :" + aClass.message_html);
Console.WriteLine("--------------------------");
Console.Read();
}
}
public class MyClass
{
public int post_id { get; set; }
public int thread_id { get; set; }
public int user_id { get; set; }
public string username { get; set; }
public int post_date { get; set; }
public string message { get; set; }
public int ip_id { get; set; }
public string message_state { get; set; }
public int attach_count { get; set; }
public int position { get; set; }
public int likes { get; set; }
public string like_users { get; set; }
public int warning_id { get; set; }
public string warning_message { get; set; }
public int last_edit_date { get; set; }
public int last_edit_user_id { get; set; }
public int edit_count { get; set; }
public int node_id { get; set; }
public string title { get; set; }
public string tags { get; set; }
public string node_title { get; set; }
public object node_name { get; set; }
public string message_html { get; set; }
public string absolute_url { get; set; }
}
}
OUTPUT
You can use regex to get the value you want.
string yourJsonString = #"{ ""post_id"":13, ""thread_id"":9, ""user_id"":1, ""username"":""Username"", ""post_date"":1496439611, ""message"":""testzilla - 2133746943A9"", ""ip_id"":698, ""message_state"":""visible"", ""attach_count"":0, ""position"":0, ""likes"":0, ""like_users"":""a:0:{}"", ""warning_id"":0, ""warning_message"":"""", ""last_edit_date"":1496476199, ""last_edit_user_id"":0, ""edit_count"":9, ""node_id"":34, ""title"":""Test"", ""tags"":""a:0:{}"", ""node_title"":""test node"", ""node_name"":null, ""message_html"":""testzilla - 2133746943A9"", ""absolute_url"":""url""}";
string value = System.Text.RegularExpressions.Regex.Match(yourJsonString,#"""message"":(.+?),").Groups[1].Value.Replace(#"""","");
MessageBox.Show(value);
You can also use dynamic type for deserialization. You will no need to write object for deserialization:
var str = "{\r\n \"post_id\":13,\r\n \"thread_id\":9,\r\n \"user_id\":1,\r\n \"username\":\"Username\",\r\n \"post_date\":1496439611,\r\n \"message\":\"testzilla - 2133746943A9\",\r\n \"ip_id\":698,\r\n \"message_state\":\"visible\",\r\n \"attach_count\":0,\r\n \"position\":0,\r\n \"likes\":0,\r\n \"like_users\":\"a:0:{}\",\r\n \"warning_id\":0,\r\n \"warning_message\":\"\",\r\n \"last_edit_date\":1496476199,\r\n \"last_edit_user_id\":0,\r\n \"edit_count\":9,\r\n \"node_id\":34,\r\n \"title\":\"Test\",\r\n \"tags\":\"a:0:{}\",\r\n \"node_title\":\"test node\",\r\n \"node_name\":null,\r\n \"message_html\":\"testzilla - 2133746943A9\",\r\n \"absolute_url\":\"url\"\r\n}";
dynamic obj = JsonConvert.DeserializeObject(str);
var postId = obj.post_id;
Console.WriteLine("postId:" + postId);
output:
postId:13
what am I doing wrong here? i'm trying to consume the ncaa data but I'm getting a bunch of \t and \n in my data, which makes it so I can't serialize it to an object. Here is my function, you can literally run this as it takes no credentials to get the data.
public string GetGameInfo(DateTime dt)
{
string content = string.Empty;
string url = "http://data.ncaa.com/jsonp/scoreboard/baseball/d1/2016/04/06/scoreboard.html";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.ContentType = "application/json";
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream resStream = response.GetResponseStream();
using (StreamReader sr = new StreamReader(resStream))
{
content = sr.ReadToEnd();
}
return content;
}
/// <summary>
/// Summary description for Ncaa
/// </summary>
namespace Ncaa
{
public class callbackWrapper
{
public List<scoreboard> scoreboard { get; set; }
}
public class scoreboard
{
public DateTime day { get; set; }
public List<games> games { get; set; }
}
public class games
{
public string id { get; set; }
public string conference { get; set; }
public string gameState { get; set; }
public string startDate { get; set; }
public string startDateDisplay { get; set; }
public string startTime { get; set; }
public string startTimeEpoch { get; set; }
public string currentPeriod { get; set; }
public string finalMessage { get; set; }
public string gameStatus { get; set; }
public string periodStatus { get; set; }
public string downToGo { get; set; }
public string timeclock { get; set; }
public string network_logo { get; set; }
public string location { get; set; }
public string contestName { get; set; }
public string url { get; set; }
public string highlightsUrl { get; set; }
public string liveAudioUrl { get; set; }
public string gameCenterUrl { get; set; }
//public ChampInfo champInfo { get; set; }
//public IList<object> videos { get; set; }
public home home { get; set; }
public away away { get; set; }
}
public class home
{
public string teamRank { get; set; }
public IList<int> RHEBreakdown { get; set; }
public string iconURL { get; set; }
public string name { get; set; }
public string nameRaw { get; set; }
public string nameSeo { get; set; }
public string shortname { get; set; }
public string color { get; set; }
//public Social social { get; set; }
public string description { get; set; }
public string currentScore { get; set; }
public IList<string> scoreBreakdown { get; set; }
public string winner { get; set; }
}
public class away
{
public string teamRank { get; set; }
public IList<int> RHEBreakdown { get; set; }
public string iconURL { get; set; }
public string name { get; set; }
public string nameRaw { get; set; }
public string nameSeo { get; set; }
public string shortname { get; set; }
public string color { get; set; }
//public Social social { get; set; }
public string description { get; set; }
public string currentScore { get; set; }
public IList<string> scoreBreakdown { get; set; }
public string winner { get; set; }
}
}
protected void Page_Load(object sender, EventArgs e)
{
var json = GetGameInfo(DateTime.Now);
//this one doesn't work
//JsonConvert.DeserializeObject<Ncaa.callbackWrapper>(json);
//I tried removing the /ts and ns with no luck too
json = json.Replace("\t", string.Empty).Replace("\n", string.Empty);
JsonConvert.DeserializeObject<Ncaa.callbackWrapper>(json);
}
First of all, to answer why there's bunch of \ts and \ns in the response is because they ARE in your file. Those are respectively the tab character and the new line character.
I am not sure how you parse this , but most parsers should be able to handle this. In case you wrote your own, please post that code.
If the data returned will always be of format callback(JSON) you could strip the function call and simply parse the JSON using NewtonsoftJSON
EDIT: After reviewing the added code, I can notice that you are not stripping the function call. You should remove that and try again ( e.g. try removing everything until the first ocurrence of the { character and after last, or any other way you like )
Ok, so I did get it working. Doing this to the json helped.
json = json.Replace("callbackWrapper(", string.Empty).Replace(");", string.Empty);
Then, just parsing it as a scoreboard object, instead of a callback wrapper object.
I am trying to parse a whois json response but when I try parse it I get null values.
string html;
string whoisUrl = "https://whois.apitruck.com/:google.com";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(whoisUrl);
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.ASCII))
{
html = reader.ReadToEnd();
}
}
Class1 m = JsonConvert.DeserializeObject<Class1>(html);
MessageBox.Show(m.created);
Object
class Class1
{
public string created { get; set; }
}
can anyone please point what I am doing wrong here ?
Your Class1 doesn't get the value since "created" is part of the "response" and not the root level of the JSON reponse.
You'll either need to use dynamic or create a hierarchy for the classes for a simple fix.
class Class1
{
public Response Response { get; set; }
}
class Response
{
public string created { get; set; }
}
Then you can use this:
Class1 m = JsonConvert.DeserializeObject<Class1>(html);
MessageBox.Show(m.Response.created);
UPDATE
Also, here's an example of how to use the dynamic:
var m = JsonConvert.DeserializeObject<dynamic>(html);
DateTime created = (DateTime)m.response.created;
There is nice app to convert json to .net class:
public class Registrar
{
public string id { get; set; }
public string name { get; set; }
public object email { get; set; }
public string url { get; set; }
}
public class Response
{
public string name { get; set; }
public string idnName { get; set; }
public List<string> status { get; set; }
public List<string> nameserver { get; set; }
public object ips { get; set; }
public string created { get; set; }
public string changed { get; set; }
public string expires { get; set; }
public bool registered { get; set; }
public bool dnssec { get; set; }
public string whoisserver { get; set; }
public List<object> contacts { get; set; }
public Registrar registrar { get; set; }
public List<string> rawdata { get; set; }
public object network { get; set; }
public object exception { get; set; }
public bool parsedContacts { get; set; }
}
public class RootObject
{
public int error { get; set; }
public Response response { get; set; }
}
...
RootObject result = JsonConvert.DeserializeObject<RootObject>(html);
var created = result.response.created;
So I have been able to get JSON objects for a few things, however this object is quite a bit more complex.
I'm trying to get comments from Reddit.
Here is the method I use:
public async Task<List<string>> GetComments(string currentSubreddit, string topicID)
{
string commentUrl = "http://www.reddit.com/r/" + currentSubreddit + "/comments/" + topicID + "/.json";
List<Comments> commentList = new List<Comments>();
string jsonText = await wc.GetJsonText(commentUrl);
Comments.RootObject deserializeObject = Newtonsoft.Json.JsonConvert.DeserializeObject<Comments.RootObject>(jsonText);
List<string> commentListTest = new List<string>();
//List<string> commentListTest = deserializeObject.data.children[0].data.children;
return commentListTest;
}
This is the GetJsonText method:
public async Task<string> GetJsonText(string url)
{
var request = WebRequest.Create(url);
string text;
request.ContentType = "application/json; charset=utf-8";
var response = (HttpWebResponse)await request.GetResponseAsync();
using (var sr = new StreamReader(response.GetResponseStream()))
{
text = sr.ReadToEnd();
}
return text;
}
And here is a link to the Object: http://pastebin.com/WQ8XXGNA
And a link to the jsonText: http://pastebin.com/7Kh6cA9a
The error returned says this:
An exception of type 'Newtonsoft.Json.JsonSerializationException' occurred in mscorlib.dll but was not handled in user code
Additional information: Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'JuicyReddit.Comments+RootObject' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
I'd appreciate if anybody could help me with figuring out whats wrong with this.
Thanks
There are a few problems with your code actually
public async Task<List<string>> GetComments(string currentSubreddit, string topicID)
You don't need to return a list of string here, u need to return a full object
First rename RootObject in the model to an appropriate name such as "CommentsObject"
So set up your class like so and name it CommentsObject.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YOURNAMESPACE.Comments
{
public class MediaEmbed
{
}
public class SecureMediaEmbed
{
}
public class Data4
{
public int count { get; set; }
public string parent_id { get; set; }
public List<string> children { get; set; }
public string name { get; set; }
public string id { get; set; }
public string subreddit_id { get; set; }
public object banned_by { get; set; }
public string subreddit { get; set; }
public object likes { get; set; }
public object replies { get; set; }
public bool? saved { get; set; }
public int? gilded { get; set; }
public string author { get; set; }
public object approved_by { get; set; }
public string body { get; set; }
public object edited { get; set; }
public object author_flair_css_class { get; set; }
public int? downs { get; set; }
public string body_html { get; set; }
public string link_id { get; set; }
public bool? score_hidden { get; set; }
public double? created { get; set; }
public object author_flair_text { get; set; }
public double? created_utc { get; set; }
public object distinguished { get; set; }
public object num_reports { get; set; }
public int? ups { get; set; }
}
public class Child2
{
public string kind { get; set; }
public Data4 data { get; set; }
}
public class Data3
{
public string modhash { get; set; }
public List<Child2> children { get; set; }
public object after { get; set; }
public object before { get; set; }
}
public class Replies
{
public string kind { get; set; }
public Data3 data { get; set; }
}
public class Data2
{
public string domain { get; set; }
public object banned_by { get; set; }
public MediaEmbed media_embed { get; set; }
public string subreddit { get; set; }
public object selftext_html { get; set; }
public string selftext { get; set; }
public object likes { get; set; }
public object secure_media { get; set; }
public object link_flair_text { get; set; }
public string id { get; set; }
public SecureMediaEmbed secure_media_embed { get; set; }
public bool clicked { get; set; }
public bool stickied { get; set; }
public string author { get; set; }
public object media { get; set; }
public int score { get; set; }
public object approved_by { get; set; }
public bool over_18 { get; set; }
public bool hidden { get; set; }
public string thumbnail { get; set; }
public string subreddit_id { get; set; }
public object edited { get; set; }
public object link_flair_css_class { get; set; }
public object author_flair_css_class { get; set; }
public int downs { get; set; }
public bool saved { get; set; }
public bool is_self { get; set; }
public string permalink { get; set; }
public string name { get; set; }
public double created { get; set; }
public string url { get; set; }
public object author_flair_text { get; set; }
public string title { get; set; }
public double created_utc { get; set; }
public int ups { get; set; }
public int num_comments { get; set; }
public bool visited { get; set; }
public object num_reports { get; set; }
public object distinguished { get; set; }
public Replies replies { get; set; }
public int? gilded { get; set; }
public string parent_id { get; set; }
public string body { get; set; }
public string body_html { get; set; }
public string link_id { get; set; }
public bool? score_hidden { get; set; }
public int? count { get; set; }
public List<string> children { get; set; }
}
public class Child
{
public string kind { get; set; }
public Data2 data { get; set; }
}
public class Data
{
public string modhash { get; set; }
public List<Child> children { get; set; }
public object after { get; set; }
public object before { get; set; }
}
public class CommentsObject
{
public string kind { get; set; }
public Data data { get; set; }
}
}
Make your namespace correct!
Then handle the request and deserialise into a list of commentobjects: (u can use the webclient instead of httpclient if you want, this is just an example)
private HttpClient client;
public async Task<List<CommentsObject>> GetComments()
{
client = new HttpClient();
var response = await client.GetAsync("http://www.reddit.com/r/AskReddit/comments/1ut6xc.json");
if (response.IsSuccessStatusCode)
{
string json = await response.Content.ReadAsStringAsync();
List<CommentsObject> comments = await JsonConvert.DeserializeObjectAsync<List<CommentsObject>>(json);
return comments;
}
else
{
throw new Exception("Errorhandling message");
}
}
It's not ideal (and not completely an answer but more of a work around) but I created models that mock the reddit response json to make deserialization super easy. I use JsonProperty attributes on my model properties to pretty up the models a bit.
Here are the models
And since my models directly mock the json I can just use json.net's generic deserialize method.
I had a similar problem with a dictionary - now I'm trying to populate a viewmodel, to return a JSON object to a GET request.
My viewmodel is:
public class HotelInventoryta
{
public int api_version { get; set; }
public string lang { get; set; }
public List<Hotel_List_ta> hotels { get; set; }
}
public class Hotel_List_ta
{
public int ta_id { get; set; }
public string partner_id { get; set; }
public string name { get; set; }
public string street { get; set; }
public string city { get; set; }
public string postal_code { get; set; }
public string state { get; set; }
public string country { get; set; }
public double latitude { get; set; }
public double longitude { get; set; }
public string desc { get; set; }
public string url { get; set; }
public string email { get; set; }
public string phone { get; set; }
public string fax { get; set; }
}
My DataBase model is:
[Table("tblHotel")]
public class Hotelta
{
[Key()]
[Column("hotel_id")]
public long hotel_id { get; set; }
public string hotel_name { get; set; }
public string hotel_add1 { get; set; }
public string hotel_towncity { get; set; }
public string hotel_pc { get; set; }
public string hotel_country { get; set; }
public string hotel_pass { get; set; }
public string hotel_email { get; set; }
public string hotel_tel { get; set; }
public string hotel_fax { get; set; }
}
My controller code to populate the viewmodel is:
private HoteltaContext dbh = new HoteltaContext();
//
// GET: /ta/hotel_inventory
[HttpGet]
public HotelInventoryta hotel_inventory(int api_version, string lang)
{
{
HotelInventoryta hotelinventory = new HotelInventoryta();
hotelinventory.api_version = api_version;
hotelinventory.lang = lang;
// Get data from database
var h = dbh.Hotelta.Where(x => x.hotel_id != 0).ToList();
// loop through each result, and add it to the hotelinventory.hotels model
foreach (var ht in h)
{
// I get the exception on the next line
hotelinventory.hotels.Add(new Hotel_List_ta
{
ta_id = 0,
partner_id = ht.hotel_id.ToString(),
name = ht.hotel_name,
street = ht.hotel_add1,
city = ht.hotel_towncity,
postal_code = ht.hotel_pc,
country = ht.hotel_country,
url = "http://www.me.com",
email = ht.hotel_email,
phone = ht.hotel_tel,
fax = ht.hotel_fax
});
}
return hotelinventory;
}
}
The error is:
Object reference not set to an instance of an object
Firstly, can you help me resolve the error - and if possible, confirm if the way I am reading from the database and populating the viewmodel, is the best way to do it?
Thank you, Mark
This is because the hotels property is never initialized. You could do this in the constructor of HotelInventoryta:
public class HotelInventoryta
{
public HotelInventoryta()
{
hotels = new List<Hotel_List_ta>();
}
// ...
}
Now you initialzed the property with an empty collection, so you can add items to it, rather than hotels being null which causes your exception.