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.
Related
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.
Please Help me out i am new in xamarin.forms and C# i have try every solution which is given in stackoverflow but cannot avail to solve
using (var httpClient = new HttpClient())
{
var response = httpClient.GetAsync(Url).Result;
if (response.IsSuccessStatusCode)
{
var responseContent = response.Content;
string contents = await responseContent.ReadAsStringAsync();
List<abcModel> tm = JsonConvert.DeserializeObject<List<abcModel>>(contents);
abcMaster = new ObservableCollection<SummaryModel>();
var c = tm[0].SSum.Count();
}
}
Model
public class abcModel
{
public List<SSum> SSum { get; set; }
}
public class SSum
{
public string Name{ get; set; }
}
My Json
{"a":[{"SSum":[{"Name":"Earth"}]}]}
Error:-
Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[abcModel]' 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.
Because you obviously just want to deserialize a nested part of your json, do it like this:
var result = JsonConvert.DeserializeObject<Dictionary<string, List<abcModel>>>(json);
You're missing the a property in your JSON. You can deserialize into a class that has that property:
public class MyType
{
public List<abcModel> A { get; set; }
}
JsonConvert.DeserializeObject<MyType>(json);
Or skip that property all together (#stefankmitph's answer works well), here's another alternative:
JObject obj = JObject.Parse(json);
List<abcModel> model = obj["a"].ToObject<List<abcModel>>();
Just a note: normally C# classes are PascalCased.
If you already have the JSON string you should use a generator like json2csharp to create the response DTO. This will prevent mistakes in what is a collection versus single object.
public class SSum
{
public string Name { get; set; }
}
public class A
{
public List<SSum> SSum { get; set; }
}
public class RootObject
{
public List<A> A { get; set; }
}
Now you can deserialize the complete object:
tm = JsonConvert.DeserializeObject<RootObject>(contents);
I have a function that accesses a API and retrieves some Json values, these values are returned and pasted into a rich textbox. How am I able to convert this Json into a object list? The internet is filled with what i am asking but i'm not getting any wiser after reading and trying it all.
This is the function, URL is the Api link that retrieves the Json.
public string 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);
return reader.ReadToEnd();
}
}
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;
}
}
This is the Json structure
{"id":19684,"buys":[{"listings":10,"unit_price":94,"quantity":2498},{"listings":42,"unit_price":93,"quantity":10398},{"listings":139,"unit_price":92,"quantity":34501},{"listings":8,"unit_price":91,"quantity":1939},{"listings":38,"unit_price":90,"quantity":9270},{"listings":7,"unit_price":89,"quantity":1266},{"listings":43,"unit_price":88,"quantity":10565},{"listings":23,"unit_price":87,"quantity":5476},{"listings":80,"unit_price":86,"quantity":19827},
The first order of business is to use a library to parse the JSON. For this answer I use Newtonsoft.Json, one of the most used JSON libraries for .NET.
Then, the structure of the document you receive from the server should be identified. I'm just guessing here, but I assume it's something like the classes defined below. The JsonProperty is an attribute to specify the field name from the JSON document mapping to the property. It isn't necessary to specify this, only when your property names are different from the field names in the JSON document. In this case, unit_price does not match the standard .NET PascalCase naming convention for properties.
public class Listings
{
[JsonProperty(PropertyName = "id")]
public int Id { get; set; }
public List<Buy> Buys { get; private set; }
public Listings()
{
Buys = new List<Buy>();
}
}
public class Buy
{
[JsonProperty(PropertyName = "listings")]
public int Listings { get; set; }
[JsonProperty(PropertyName = "unit_price")]
public int UnitPrice { get; set; }
[JsonProperty(PropertyName = "quantity")]
public int Quantity { get; set; }
}
Once you have defined the class structure, you can let the library do all of the work. Look into the documentation for more details, here is how you would retrieve the list inside the method you already wrote.
public Listings GetApi(string url)
{
...
using (Stream responseStream = response.GetResponseStream())
{
StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);
var jsonReader = new JsonTextReader(reader);
var serializer = new JsonSerializer();
return serializer.Deserialize<Listings>(jsonReader);
}
...
}
I am stuck in a step that I am sure should work. I have a method (in a separate class) that should return a List as its value after processing the JSON. I am going to paste the code skipping the JSON configuration stuff:
public static dynamic CustInformation(string Identifier)
{
//SKIPPED JSON CONFIG STUFF (IT'S WORKING CORRECTLY)
var result = "";
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
dynamic d;
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
result = streamReader.ReadToEnd();
}
return JsonConvert.DeserializeObject<List<Models.RootObject>>(result);
}
The model was generated using C# to Json converter:
public class Record
{
public string idIdentifier { get; set; }
public string KnowName1 { get; set; }
public string KnowAddress1 { get; set; }
public string KnowRelation1 { get; set; }
public string KnowPhone1 { get; set; }
public string KnowName2 { get; set; }
public string KnowAddress2 { get; set; }
//.....skipped other variables
}
public class RootObject
{
public List<Record> record { get; set; }
}
And I am calling the method like this:
var model = Classes.EndPoint.CustInformation(identifier);
Yet I am getting this error everytime:
Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[Models.RootObject]' 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<T>) 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.
Path 'record', line 1, position 10.
EDIT: JSON
{
"record": [
{
Identifier": "DQRJO1Q0IQRS",
"KnowName1": "",
"KnowAddress1": "",
"KnowRelation1": "",
"KnowPhone1": "",
"KnowName2": "",
"KnowAddress2": "",
//.....MORE STYFF
}
]
}
Like I said in the comments, and like the error message clearly states, you're trying to deserialize into a list of root objects, but your JSON is only one root object, not an array.
Here's what your C# should be.
return JsonConvert.DeserializeObject<Models.RootObject>(result);
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