I am pulling data from API. I am getting an error while deserializing. please help me.
error:
System.Text.Json.JsonException: '',' is invalid after a single JSON value. Expected end of data. Path: $ | LineNumber: 0 | BytePositionInLine: 128.'
data i pull:
{"firmano":128257,"adi":"- FATİH YILMAZ"},{"firmano":128446,"adi":"-MEHMET ÜSTÜN"}
my c# codes:
Index.cs :
var result = await Api<Company>.pullDataAsync("https://localhost:5001/api/PesinIskontolar/companyGet");
api.cs:
public class Api<T> where T : class
{
public async static Task<T> pullDataAsync(string url)
{
var client = new RestClient(url);
var request = new RestRequest(Method.GET);
IRestResponse response = await client.ExecuteAsync(request);
return Json_Convert<T>.deserializeProcess(apiFormat(response.Content));
}
public static string apiFormat(string response)
{
var result = response.Replace("\\", "").Replace("[","").Replace("]","");
return result.Substring(1, result.Length - 2);
}
}
Json_Convert.cs:
public class Json_Convert<T> where T : class
{
public static T deserializeProcess(string response)
{
return JsonSerializer.Deserialize<T>(response);
}
}
dal:
public string getCompany()
{
......
DataTable dt = new DataTable();
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dt);
string data = JsonConvert.SerializeObject(dt);
baglanti.Close();
baglanti.Dispose();
return data;
}
api:
[HttpGet("companyGet")]
public IActionResult companyGet()
{
return Ok(_firmaServices.getCompany());
}
Since some friends said that there is a problem with the api, I added other codes.
company class:
public class Company
{
public int firmano { get; set; }
public string adi { get; set; }
}
Your JSON is invalid, should be:
[{"firmano":128257,"adi":"- FATİH YILMAZ"},{"firmano":128446,"adi":"-MEHMET ÜSTÜN"}]
instead of:
{"firmano":128257,"adi":"- FATİH YILMAZ"},{"firmano":128446,"adi":"-MEHMET ÜSTÜN"}
Also, instead of calling response.Content prior to deserialization, you need to call await response.Content.ReadAsStringAsync() method to actually read the returning json string from the server.
As you pulling a list of two companies, your deserialization should be deserializing to a list instead of a single object, so you need to delete the apiFormat method and call await Api<IEnumerable<Company>>.pullDataAsync instead of await Api<Company>.pullDataAsync
You should deserialize List< Company >, not just Company so use this code
var result = await Api<List<Company>>.pullDataAsync("https://localhost:5001/api/PesinIskontolar/companyGet");
and fix your generic code by removing apiFormat(response.Content), replace it by just content. it will prevent removing [] from your json, this is what causes an exception
public async static Task<T> pullDataAsync(string url)
{
var client = new RestClient(url);
var request = new RestRequest(Method.GET);
IRestResponse response = await client.ExecuteAsync(request);
return Json_Convert<T>.deserializeProcess(response.Content); //fix here!!!
}
and according to your response.Content, you company class should be changed
public partial class Company
{
[JsonPropertyName("firmano")]
public int firmano { get; set; }
[JsonPropertyName("Column1")]
public string adi { get; set; }
}
1.Try to use known class as Company instate of
2.Json converter does not like special characters like '(Some times People are using the ' char, to write a letter like è, and this can bracke the Json String). You can do like .Replace("'", "''")
3.Use encoding UTF8.
4.Control the API Site in Debug and see the Response creation..
5. before subtracting the end 2 chars check if the string has this chars. better do this operations after you get the response.
return result.Substring(1, result.Length - 2);
Related
I have an API method that looks like this:
[HttpGet("top/{max}", Name = "GetTopLocations")]
public ActionResult<List<LocationDto>> GetTop(int max)
{
return _locationService.Get();
}
I have then generated client code class with NSwag via Swagger. I call this method in my Blazor WebAssembly code like this:
Locations = await MyProject.Client.GetTopLocationsAsync(10);
However, this generates an exception:
Error: 0 : Could not deserialize the response body stream as System.Collections.Generic.ICollection`1[[MyProject.LocationDto, MyProject.Client, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].
But if I call this method in my browser like this: http://localhost:50464/api/Locations/top/10
and then take that JSON string and test to Deserialize it like this:
string jsonStringCopiedFromBrowser = "...";
var thisWorks = JsonConvert.DeserializeObject<ICollection<LocationDto>>(jsonStringCopiedFromBrowser);
I cannot understand why it works when I deserialize it like in the last code but not from NSwag? Any tips on what I am doing wrong? I have not modified the NSwag generated code at all, its taken directly from the generated output.
NSwag Studio does not help with this kind of operation.
so you need to create a List mannunally.
I try and its work
here is the code below
public class Response<T>
{
public string Message { get; set; }
public string ValidatonError { get; set; }
public bool Success { get; set; }
public T Data { get; set; }
public IList<T> DataEnum { get; set; }
}
public async Task<Response<EmployeeDetailDTO>> GetEmployee(int ID)
{
Response<EmployeeDetailDTO> response;
try
{
var data = await client.EmployeeAllAsync(ID);
response = new Response<EmployeeDetailDTO>
{
DataEnum = data.ToList(),
Success = true
};
}
catch (ApiException e)
{
response = ConvertApiException<EmployeeDTO>(e);
}
return response;
}
Now extract the result on your Client Page
#foreach(var model in rl.ToArray())
{
<td>#model.Complaintname</td>
}
after a couple of hours, I use this method for solving the problem. NSwag Studio work if you send a single Record.
I need to wrap an api call with my own api to avoid CORS and so I can avoid exposing credentials to the client. Can anyone help me to figure out what I'm doing wrong?
This works in a webform but I don't know how to put its an api controller class.
When I try to return the objects with the code below it throws an error
Controller:
public class sampleController : ApiController
{
public IEnumerable<sample> GetSample()
{
string url = String.Format("sampleurl.json");
WebRequest requestObj = WebRequest.Create(url);
requestObj.Credentials = new NetworkCredentials("USER", "PW");
requestObj.Method = "GET";
HttpWebResponse responseObj = null;
responseObj = (HttpWebResponse)requestObj.GetResponse();
string str = null;
using (Stream stream = responseObj.GetResponseStream())
{
StreamReader sr = new StreamReader(stream);
str = sr.ReadToEnd();
sr.Close();
}
var ser = new System.Web.Script.Serialization.JavaScriptSerializer();
sample sampleList = (sample).ser.Deserializer(str, typeof(sample));
return sampleList.Root_Object;
}
}
Model:
public class sample
{
public List<Root_Object> Root_Object {get; set;}
}
public class Root_Object
{
public string listItemOne { get; set; }
public string listItemTwo { get; set; }
}
JSON
{
"Root_Object": [
{
"ListItemOne": "Value",
"ListItemTwo": "Value"
},
{
"ListItemOne": "Value",
"ListItemTwo": "Value"
},
{
"ListItemOne": "Value",
"ListItemTwo": "Value"
}
]
}
I expected to be able to return all objects from Root_Object. The return statement gives me an error of
"Cannot implicitly convert type 'System.Collections.Generic.IList<project.Models.Root_Object>' to 'System.Collections.Generic.IEnumerable<project.Models.sample>'. An explicit conversion exists(are you missing a cast?)"
Assuming the GetSample() method is supposed to be a pass-through API, meaning you don't intend to change the JSON format at all, then you need to make two changes:
Change the return type of your method from IEnumerable<sample> to sample
Change the method to return sampleList instead of sampleList.Root_Object.
If you're instead trying to "unwrap" the list of objects, then the other two answers are correct.
Should you not be returning IEnumerable<Root_Object> as the type? You currently have it as IEnumerable<sample>.
Your method requires a return type of IEnumerable<sample>, but you are returning sampleList.Root_Object, which is itself a list of Root_Object
Newbie in this so sorry for the mistakes.
I have a C# app that is running and calling python functions. the functions is being called using POST method. In addition, I would like that this call will reply from python to C# object which include 4 arrays. I successfully did passing a simple string but when I am trying to pass an object, it doesnt work. Here is the code:
C# caller side
public class RootObject
{
public Array b1 { get; set; }
public Array cl { get; set; }
public Array sc { get; set; }
}
public static List<RootObject> post(string path, int Port)
{
var client = new RestClient("http://localhost:" +
Port.ToString());
var request = new RestRequest("/postmethod", Method.POST);
request.AddHeader("content-type", "application/form-data");
request.AddFile("file", path);
IRestResponse response = client.Execute(request);
var json = response.Content;
var content = response.Content; // raw content as string
List<RootObject> r;
r = JsonConvert.DeserializeObject<List<RootObject>>(json);
return r;
}
Python side
class myscoresobj:
def __init__(self):
self.b1
self.cl
self.sc
#app.route('/postmethod', methods=['POST'])
def index():
if 'file' not in request.files:
return "file not found"
file = request.files['file']
contents = file.read()
....
myscoresobj = worker(input_q, output_q)
return str(myscoresobj )
Any way how to solve this?
We have got a Odata response as below:
"{\r\n \"#odata.context\":\"http://localhost/ApplicationService/model/$metadata#Edm.String\",\"value\":\"{\\\"Messages\\\":[\\\"message 1\\\",\\\"message 2\\\",\\\"message 3\\\",\\\"message 4\\\"],\\\"IsValidEntity\\\":false}\"\r\n}"
Now say we have a class:
public class myValidationResult
{
public myValidationResult()
{
Messages = new List<string>();
}
public List<string> Messages { get; set; }
public bool IsValidEntity { get; set; }
}
This class used in MyOdataController class as below:
public class MyODataController : ODataController
{
[Authorize(Roles = "Admin")]
public async Task<IHttpActionResult> Post(T entity)
{
myValidationResult vResult = new myValidationResult();
vResult.Messages.Add("message 1");
vResult.Messages.Add("message 2");
vResult.Messages.Add("message 3");
vResult.Messages.Add("message 4");
vResult.IsValidEntity = false;
var strResult = JsonConvert.SerializeObject(vResult);
var resp = Content(HttpStatusCode.BadRequest, strResult );
return resp;
}
}
For the client Consuming this, we created below Class:
public class OData<T>
{
[JsonProperty("odata.context")]
public string Metadata { get; set; }
public T value { get; set; }
}
In the method where we call the Odata method & store response in 'msg':
var resp = msg.Result.Content.ReadAsStringAsync().Result;
resp is:
"{\r\n \"#odata.context\":\"http://localhost/ApplicationService/model/$metadata#Edm.String\",\"value\":\"{\\\"Messages\\\":[\\\"message 1\\\",\\\"message 2\\\",\\\"message 3\\\",\\\"message 4\\\"],\\\"IsValidEntity\\\":false}\"\r\n}"
var odatares = JsonConvert.DeserializeObject<OData<myValidationResult>>(resp);
But the above line giving error:
Can not convert value\":\"{\\\"Messages\\\":[\\\"message 1\\\",\\\"message 2\\\",\\\"message 3\\\",\\\"message 4\\\"],\\\"IsValidEntity\\\":false} to <.....namespace......>myValidationResult
Please suggest accordingly.
The OData response contains a string, not an instance of myValidationResult. Also, the response looks like it's missing some backslashes. (Are you sure the response shown is exactly what you received from the service?)
You can either fix the serialization of myValidationResult on the service:
// Don't serialize vResult yourself. OData will do it for you.
var resp = Content(HttpStatusCode.BadRequest, vResult );
Or deserialize in two steps as follows.
var data = "{\r\n \"#odata.context\":\"http://localhost/ApplicationService/model/$metadata#Edm.String\",\"value\":\"{\\\"Messages\\\":[\\\"message 1\\\",\\\"message 2\\\",\\\"message 3\\\",\\\"message 4\\\"],\\\"IsValidEntity\\\":false}\"\r\n}";
var outer = Newtonsoft.Json.JsonConvert.DeserializeObject<OData<string>>(data);
var inner = Newtonsoft.Json.JsonConvert.DeserializeObject<myValidationResult>(outer.value);
One more thing: The JsonProperty on OData<T> should be named #odata.context.
In my case the OData response did not contain a string but an object array which contains the data string as its first element. So in this case reading the data should look like this:
var outer = Newtonsoft.Json.JsonConvert.DeserializeObject<OData<object[]>>(data);
var inner = Newtonsoft.Json.JsonConvert.DeserializeObject<myValidationResult>(outer.value[0].ToString());
I manged to get my json returned but I am having trouble returning it back into my class says cause its array. But I am using a deserialize method helper i studied from books. And should work.
So the question I need answered is how does my class need to be properly structured to decode the json into the city object.
I am grabbing my json via method which works
/// <summary>
/// Utility function to get/post WCFRESTService
/// </summary>
/// <param name="methodRequestType">RequestType:GET/POST</param>
/// <param name="methodName">WCFREST Method Name To GET/POST</param>
/// <param name="bodyParam">Parameter of POST Method (Need serialize to JSON before passed in)</param>
/// <returns>Created by David</returns>
private async Task<string> WCFRESTServiceCall(string methodRequestType, string methodName, string bodyParam = "")
{
string ServiceURI = "/launchwebservice/index.php/webservice/" + methodName;
HttpClient httpClient = new HttpClient();
HttpRequestMessage request = new HttpRequestMessage(methodRequestType == "GET" ? HttpMethod.Get : HttpMethod.Post, ServiceURI);
if (!string.IsNullOrEmpty(bodyParam))
{
request.Content = new StringContent(bodyParam, Encoding.UTF8, "application/json");
}
HttpResponseMessage response = await httpClient.SendAsync(request);
string jsongString = await response.Content.ReadAsStringAsync();
return jsongString;
}
Then I am using the deserialize method
public static class Helpers
{
public static List<T> Deserialize<T>(this string SerializedJSONString)
{
var stuff = JsonConvert.DeserializeObject<List<T>>(SerializedJSONString);
return stuff;
}
}
I am calling the above in the following manner
string jsonresult = await WCFRESTServiceCall("GET", "cinema_city");
var data = jsonresult.Deserialize<Citys>();
var dialog = new MessageDialog(jsonresult);
await dialog.ShowAsync();
Which when I check jsonresult it is indeed returning the json but in square brackets for some reason.
Which gives me the following error:
My Class of city is as follows
public class City
{
public string id { get; set; }
public string timing_title { get; set; }
}
public class Citys
{
public List<City> city { get; set; }
}
Edit To Show The jason data
{"city":[{"id":"5521","timing_title":"Lahore"},{"id":"5517","timing_title":"Karachi"},{"id":"5538","timing_title":"Islamabad"},{"id":"5535","timing_title":"Rawalpindi"},{"id":"5518","timing_title":"Hyderabad"},{"id":"5512","timing_title":"Faisalabad"},{"id":"8028","timing_title":"Gujranwala"},{"id":"8027","timing_title":"Gujrat"}]}
Edit to show error
Error on dezerilize event ?
For your classes json going to be:
For City class
{ id: "some string", timing_title:"some string" }
and for Citys class:
{ city: [ { id: "some string", timing_title:"some string" }, ... ] }
I belive you have a typo in property name - it is city now, but really should be cities.
Another issue I see is that you are mixing together Citys class and List. They are not the same and you cannot serialize/deserialize them to each other.
Correct json for List going to be:
[ { id: "some string", timing_title:"some string" } ,... ]
compare it to Citys class above.
UPDATE: After reading it again, you are trying to deserialize List to Citys. That is what your exeption says. Probably that is what you wanted to say:
public static class Helpers
{
public static T Deserialize<T>(this string SerializedJSONString)
{
var stuff = JsonConvert.DeserializeObject<T>(SerializedJSONString);
return stuff;
}
}
string jsonresult = await WCFRESTServiceCall("GET", "cinema_city");
var data = jsonresult.Deserialize<Citys>();
var dialog = new MessageDialog(jsonresult);
await dialog.ShowAsync();