Deserializing JSON to List<> is not working in C# - c#

This is the JSON i got from stream, and converted to string.
"{\"data\":[{\"thread_id\":\"1111155552222\",\"recipients\":[123123,456456],\"message_count\":2100},{\"thread_id\":\"1111155553333\",\"recipients\":[123124,456457],\"message_count\":4851},{\"thread_id\":\"1111155554444\",\"recipients\":[123125,456458],\"message_count\":435}]}"
public class DataContainer
{
List<data> data { get; set; }
}
public class data
{
public string thread_id { get; set; }
public long[] recipients { get; set; }
public int message_count { get; set; }
}
JavaScriptSerializer ser = new JavaScriptSerializer();
DataContainer data = ser.Deserialize<DataContainer>(json);
I am getting null at data, it does not seem to get deserialize. amateur in json. getting headache with this already.
Thanks!
Getting the JSON string
WebResponse response = request.GetResponse();
Stream stream = response.GetResponseStream();
Encoding encode = System.Text.Encoding.GetEncoding("utf-8");
StreamReader reader = new StreamReader(stream, encode);
string json = reader.ReadToEnd();

It seems your "JSON you got from stream and converted to string" has been serialized twice.
ASP.NET automatically JSON serializes your service methods’ responses, even if their result is an object or collection of objects
You should be able to use it directly without having to serialize/deserialize it.
Something like:
//Assuming GetJson() returns a JSON string, which you can use directly
DataContainer data = GetJson();
Check this: http://encosia.com/asp-net-web-services-mistake-manual-json-serialization/
Also this: Reading from JSON, data not displayed

Related

unable to put deserialized json into gridview

Gridview unable to get json data due to invalid data type. From what i understand it needs a List<> data source. How do i make my data populate my gridview?
The received JSON from the api
{"BTC":{"SGD":4864.11,"USD":3617.33,"EUR":3162.71}}
...
public class BTC
{
public double SGD { get; set; }
public double USD { get; set; }
public double EUR { get; set; }
}
public class CryptoPrice
{
public BTC BTC { get; set; }
}
...
var webRequest = (HttpWebRequest)WebRequest.Create("https://min-api.cryptocompare.com/data/pricemulti?fsyms=BTC&tsyms=SGD,USD,EUR&api_key=<secret_key>");
var webResponse = (HttpWebResponse)webRequest.GetResponse();
if (webResponse.StatusCode == HttpStatusCode.OK)
{
JavaScriptSerializer json = new JavaScriptSerializer();
StreamReader sr = new StreamReader(webResponse.GetResponseStream());
string resString = sr.ReadToEnd();
CryptoPrice list = json.Deserialize<CryptoPrice>(resString);
GridView1.DataSource = list.BTC;
GridView1.DataBind();
}
I’m not 100% sure but your data source is not a list. As you can see in your code you’re deserializing returned Json to only one instance of CryptoPrice type. Try deserializing it to List<CryptoPrice> and assign it as data source to your grid view.

WCF Deserialize JSON String

I had edited my question :
How can i deserialize the JSON string shows below :
"{\"acctId\": \"Test10001\",\"amount\": 200,\"currency\": \"USD\",\"Code\": \"Test\",\"serialNo\": \"1234566789asdsad0\"}"
Please give suggestion how can I get the data by using this method or any other recommended method.
Suggesting you to use StreamWriter as below.
Use this function and pass your string and return a the Stream which will give you the desired JSON Content
public static Stream GenerateStreamFromString(string s)
{
MemoryStream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
writer.Write(s);
writer.Flush();
stream.Position = 0;
return stream;
}
The payload of your POST request seems to be in JSON format, so you should use a JSON parsing library to parse it, such as Json.NET. Then you would write something like:
JsonConvert.DeserializeObject<YourRequestObject>(res)
I think below code should serve your purpose:
public class DeserializedData
{
public string acctId { get; set; }
public string amount { get; set; }
public string currency { get; set; }
public string Code { get; set; }
public string serialNo { get; set; }
}
StreamReader reader = new StreamReader(streamdata);
string res = reader.ReadToEnd();
Use third party dlls like Json.NET or Restsharp:
1.) Using Json.Net Json.NET
var result = JsonConvert.DeserializeObject<DeserializedData>(res);
2.) Using Restsharp Restsharp
var jsonDeserializer = new RestSharp.Deserializers.JsonDeserializer();
var response = jsonDeserializer.Deserialize<DeserializedData>(res);
Let me know if it doesn't work for you.
you can read Json string like this
dynamic stuff = JObject.Parse(res.ToString());
string acctId= stuff.acctId;
But the response string you are parsing should be json formatted.

Read specific object data from json

I want to get specific object data from json from url the following code give me. i need the second object 'EmailAddressSuffices'
WebRequest request = WebRequest.Create(
"https://atea-dev.accesscontrol.windows.net/v2/metadata/IdentityProviders.js?protocol=wsfederation&realm=https%3a%2f%2flocalhost%3a44300%2fAccount%2fLoginCallback%2f&reply_to=https%3a%2f%2flocalhost%3a44300%2fAccount%2fLoginCallback%2f&context=&request_id=&version=1.0&callback=");
request.Credentials = CredentialCache.DefaultCredentials;
WebResponse response = request.GetResponse();
Stream dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
string responseFromServer = reader.ReadToEnd();
Using JSON.Net you can deserialize the JSON response easily:
Solution 1
1. Create a class to map your JSON into:
public class ResponseObject
{
[JsonProperty("Name")]
public string Name { get; set; }
[JsonProperty("LoginUrl")]
public string LoginUrl { get; set; }
[JsonProperty("LogoutUrl")]
public string LogoutUrl { get; set; }
[JsonProperty("ImageUrl")]
public string ImageUrl { get; set; }
[JsonProperty("EmailAddressSuffixes")]
public IList<string> EmailAddressSuffixes { get; set; }
}
2. Deserialize your JSON using JsonConvert.Deserialize<ResponseObject>()
var myresponse = JsonConvert.DeserializeObject<List<ResponseObject>>(responseFromServer);
string email = myresponse[1].EmailAddressSuffixes[0];
Solution 2
If you don't want to bother with derializing the entire thing then you can do this:
JArray array = JArray.Parse(responseFromServer);
string q = array[1]["EmailAddressSuffixes"][0].ToString();
But you should make sure that your object has the right format (and the right number of items in the array.

Windows App - Using XML in textbox

[DataContract]
public class RootObject
{
[DataMember]
public int RecipeID { get; set; }
[DataMember]
public string Title { get; set; }
[DataMember]
public string Description { get; set; }
[DataMember]
public string Cuisine { get; set; }
[DataMember]
public string Category { get; set; }
[DataMember]
}
public async static Task<RootObject> GetRecipe()
{
var http = new HttpClient();
var url = String.Format("http://api.bigoven.com/recipe/196149?api_key=//apikey");
var response = await http.GetAsync(url);
var result = await response.Content.ReadAsStringAsync();
XmlSerializer serializer = new XmlSerializer(typeof(RootObject));
var ms = new MemoryStream(Encoding.UTF8.GetBytes(result));
XmlReader reader = XmlReader.Create(ms);
RootObject i;
i = (RootObject)serializer.Deserialize(reader);
return i;
}
I use the above method in a bigoven class which gets the data of a recipe as XML data such as:
<Recipe xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<RecipeID>196149</RecipeID>
<Title>Lasagna</Title>
<Cuisine>Italian</Cuisine>
and I would like to put the data for the title and cuisine into textboxes, however when I try the method below I get the error "Recipe xmlns='' was not expected."
RootObject myRecipe = await bigoven.GetRecipe();
textBox.Text = myRecipe.Title;
Answered before. Basically this:
When serialising an XML document to a .NET string, the encoding must be set to UTF-16. Strings are stored as UTF-16 internally, so this is the only encoding that makes sense. If you want to store data in a different encoding, you use a byte array instead.
See the entire thread here:
Using StringWriter for XML Serialization
It looks like your Json serializer might be trying to deserialize xml data.
You might try looking at the raw string in result and making sure that it's actually JSON data. If it's not, you need to find the appropriate deserailizer to use.
I'm guessing result contains XML in which case you'd need to use an XML Deserializer to convert it to a RootObject
Here's the link for the .NET one:
https://msdn.microsoft.com/en-us/library/tz8csy73(v=vs.110).aspx

c# Deserialize json into List

I have this code that retrieves Json string from API link. The Json is deserialized and returned to a textbox. This works perfectly as long as there is only 1 Json value, being returned more than 1 value it crashes with this error:
Additional information: Cannot deserialize the current JSON array
(e.g. [1,2,3]) into type 'GW2_tradingPost.RootObject' 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.
Doing my research this happens because there is nowhere to deposit the Json since its not an List.
I've have tried this code and various similar ones.
List<RootObject> list = JsonConvert.DeserializeObject<List<RootObject>>(jsonReader.ToString());
return list;
This will return with error:
Error 1 Cannot implicitly convert type
'System.Collections.Generic.List' to
'GW2_tradingPost.RootObject' e:\mega\gw2_tradingpost\gw2_tradingpost\api_request.cs 34
Which i dont fully understand what it means.
Here is my full code.
api_Request.cs
public class api_Request
{
public RootObject GetApi(string url)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
try
{
WebResponse response = request.GetResponse();
using (Stream responseStream = response.GetResponseStream())
{
StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);
var jsonReader = new JsonTextReader(reader);
var serializer = new JsonSerializer();
return serializer.Deserialize<RootObject>(jsonReader);
}
}
catch (WebException ex)
{
WebResponse errorResponse = ex.Response;
using (Stream responseStream = errorResponse.GetResponseStream())
{
StreamReader reader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8"));
String errorText = reader.ReadToEnd();
// log errorText
}
throw;
}
}
}
public class Buy
{
public int listings { get; set; }
public int unit_price { get; set; }
public int quantity { get; set; }
}
public class Sell
{
public int listings { get; set; }
public int unit_price { get; set; }
public int quantity { get; set; }
}
public class RootObject
{
public int id { get; set; }
public List<Buy> buys { get; set; }
public List<Sell> sells { get; set; }
}
Form1.cs
private void button1_Click(object sender, EventArgs e)
{
RootObject RootObject = new RootObject();
api_Request api_Request = new api_Request();
richTextBox1.Text = api_Request.GetApi("https://api.guildwars2.com/v2/commerce/listings").id.ToString();
}
In this json is a single ID, so this works fine. https://api.guildwars2.com/v2/commerce/listings/19684
But when retrieving multiple ID's like here, it breaks.
https://api.guildwars2.com/v2/commerce/listings
Here is a simple solution to get listing of all id's it will a real amount of time though to go through all of them
List<RootObject> rootobject = new List<RootObject>();
using (var webclient = new WebClient())
{
var Ids = webclient.DownloadString(" https://api.guildwars2.com/v2/commerce/listings");
foreach (var id in Ids.Substring(1, s.Length-2).Split(','))
{
string url = string.Format("{0}/{1}","https://api.guildwars2.com/v2/commerce/listings",id);
var res = webclient.DownloadString(url);
var jsonObject = JsonConvert.DeserializeObject<RootObject>(res);
rootobject.Add(jsonObject);
}
}
The link that you provided for multiple ID's return an Array of Integers. I would suggest parsing this as such:
var ids = JsonConvert.DeserializeObject<int[]>(jsonReader.ToString())
As you have said, your code works for a single item, so you can use your existing code for each individual request which instead of hitting https://api.guildwars2.com/v2/commerce/listings, will be hitting https://api.guildwars2.com/v2/commerce/listings/{id} which you can use string.Format() to add where it is needed.
Seriously consider how many of the id's returned in the int[] you actually want to fetch the root object for though, as from what I can see that it returns, you will be making a hell of a lot of requests.

Categories