c# json json.net parse to class - c#

For some time I have a problem with the code.
Trying to retrieve data from the API using the json but when trying to parse json and send it to the class I receives empty string.
The json data looks like this
{"Wynik":{"Token":"String","DataCzasWaznosci":"\/Date(-62135596800000-0000)\/"}
... and this is my code:
public void post()
{
Autoryzacja_zaloguj a_zaloguj = new Autoryzacja_zaloguj();
string url = a_zaloguj.Link;
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
byte[] requestBytes = System.Text.Encoding.ASCII.GetBytes(a_zaloguj.Json);
req.Method = "POST";
req.ContentType = "application/json";
req.ContentLength = requestBytes.Length;
Stream requestStream = req.GetRequestStream();
requestStream.Write(requestBytes, 0, requestBytes.Length);
requestStream.Close();
HttpWebResponse res = (HttpWebResponse)req.GetResponse();
StreamReader sr = new StreamReader(res.GetResponseStream(), System.Text.Encoding.Default);
string backstr = sr.ReadToEnd();
dynamic d = JObject.Parse(backstr);
var wynik = d.Wynik;
string token = wynik.Token;
DateTime data = wynik.DataCzasWaznosci;
Wyniki wyniki = new Wyniki();
wyniki.test = token;
sr.Close();
res.Close();
}
public class Wyniki
{
public string test { get; internal set; }
}

You could use Newtosoft nugget package for this kind of parsing
http://www.newtonsoft.com/json
public class Wynik
{
public string Token { get; set; }
public DateTime DataCzasWaznosci { get; set; }
}
/*Deserialization part */
string backstr = sr.ReadToEnd();
Wynikm = JsonConvert.DeserializeObject<Wynik>(backstr);

Related

XmlException: Root element is missing. Stream and XmlSerializer

I am trying to run this app (code from net)but getting error XmlException: Root element is missing. Where am I doing wrong? (I am learning to work with XML requests).
Method:
public static T postXMLData<T>(string xml)
{
Console.WriteLine(xml);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Requests.url);
byte[] bytes;
bytes = System.Text.Encoding.ASCII.GetBytes(xml);
request.ContentType = "text/xml; encoding='utf-8'";
request.ContentLength = bytes.Length;
request.Method = "POST";
Stream requestStream = request.GetRequestStream();
requestStream.Write(bytes, 0, bytes.Length);
requestStream.Close();
HttpWebResponse response;
response = (HttpWebResponse)request.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
{
Stream responseStream = response.GetResponseStream();
string responseStr = new
StreamReader(responseStream).ReadToEnd();
Console.WriteLine(responseStr);
var xmlSerializer = new XmlSerializer(typeof(T));
var t = (T)xmlSerializer.Deserialize(responseStream); //error here
return t;
}
throw new Exception("что то не так");
}
When I run app:
static void Main(string[] args)
{
var req = postXMLData<Responses.Response>(Requests.checkRequest());
if (req.result==0)
Console.WriteLine("ok");
Console.ReadKey();
}
Requests class:
public static string checkPaymentRequisites(string payId, string service, string account, string amount)
{
string req = authReq + $"<providers> <checkPaymentRequisites> <payment id=\"{payId}\"> <from currency=\"{currency}\" amount=\"{amount}\"/> <to currency=\"{currency}\" service=\"{service}\" amount=\"{amount}\" account=\"{account}\" moneyType=\"{moneyType}\"/> <receipt id=\"{receiptId}\" date=\"{dTime}\"/> </payment> </checkPaymentRequisites> </providers> </request>";
return req;
Responses class:
[XmlRoot(ElementName = "payment")]
public class Payment
{
[XmlAttribute(AttributeName = "date")]
public DateTime date { get; set; }
[XmlAttribute(AttributeName = "fatal")]
public string fatal { get; set; }
[XmlAttribute(AttributeName = "id")]
public string id { get; set; }
[XmlAttribute(AttributeName = "result")]
public int result { get; set; }
[XmlAttribute(AttributeName = "saved")]
public bool saved { get; set; }
[XmlAttribute(AttributeName = "status")]
public int status { get; set; }
[XmlAttribute(AttributeName = "uid")]
public long uid { get; set; }
}
[XmlRoot(ElementName = "checkPaymentRequisites")]
public class checkPaymentRequisites
{
[XmlElement(ElementName ="payment")]
public Payment Payment { get; set; }
[XmlElement(ElementName ="extras")]
public Extras Extras { get; set; }
[XmlAttribute(AttributeName ="result")]
public int result { get; set; }
}
[XmlRoot(ElementName = "providers")]
public class Providers
{
[XmlElement(ElementName = "checkPaymentRequisites")]
public checkPaymentRequisites checkPaymentRequisites { get; set; }
}
[XmlRoot(ElementName ="response")]
public class Response
{
[XmlElement(ElementName ="providers")]
public Providers Providers { get; set; }
[XmlAttribute(AttributeName ="result")]
public int result { get; set; }
//[XmlText]
//public string Text { get; set; }
}
The main goal of the app is to deserialize and to display Response from Request in XML.
This problem "XmlException: Root element is missing" is because you do not create a XML document from the response stream. The right code is as below:
...
string xml = HttpUtility.UrlDecode(responseStream.Substring(responseStream.IndexOf("XML=") + 4));
XmlDocument document = new XmlDocument();
document.LoadXml(xml);
T result = new T();
XmlNode newNode = document.DocumentElement;
result.Name = ((XmlAttribute)newNode.Attributes["Name"]).InnerText;
result.ID = ((XmlNode)newNode.FirstChild).InnerText;
using (TextReader reader = new StringReader(xml))
{
var serializer = new XmlSerializer(typeof(T));
result = (T)serializer.Deserialize(reader);
}
return result;
Your issue is that you are trying to read the response twice. The stream can only be read once.
So either you can just deserialize it
using var responseStream = response.GetResponseStream();
var xmlSerializer = new XmlSerializer(typeof(T));
var t = (T)xmlSerializer.Deserialize(responseStream);
Or you can first copy it into a string to dump to console, then deserialize from that string.
using var responseStream = response.GetResponseStream();
using var sr = new StreamReader(responseStream)
string responseStr = sr.ReadToEnd();
Console.WriteLine(responseStr);
var xmlSerializer = new XmlSerializer(typeof(T));
var t = (T)xmlSerializer.Deserialize(new StringReader(responseStr));
However you have a number of other serious issues in your code:
Use of WebRequest which is deprecated and really old. Use HttpClient instead.
You should use await to better manage responsiveness
You are not disposing the stream, nor many other IDisposable objects.
You should cache the XmlSerializer
You have a mismatch between the encoding you are using and the encod
private static HttpClient _client = new(); // cache the client and serializer
private static XmlSerializer _xmlSerializer = new(typeof(T));
public static async Task<T> postXMLData<T>(string xml)
{
Console.WriteLine(xml);
using var message = new HttpRequestMessage(HttpMethod.Post, Requests.url);
message.Content = new StringContent(xml, Encoding.UTF8, "text/xml; encoding='utf-8'");
using var response = await _client.SendAsync(message, HttpCompletionOption.ResponseHeadersRead);
response.EnsureSuccessStatusCode();
var responseStr = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseStr);
var t = (T)_xmlSerializer.Deserialize(responseStream);
return t;
}
static async Task Main(string[] args)
{
var req = await postXMLData<Responses.Response>(Requests.checkRequest());
if (req.result == 0)
Console.WriteLine("ok");
Console.ReadKey();
}
If you want to read it as a stream then use
using var responseStream = await response.Content.ReadAsStreamAsync();
using var sr = new StreamReader(responseStream);
var responseStr = await sr.ReadToEndAsync();

Parsing Json response from Httpwebrequest

I'm trying to parse data from a response using httpwebrequest, which is in JSON format, I've tried to use JSON.Net but seem to be having no luck, I'm open to using Regex if need be.
Example of current code -
var request = (HttpWebRequest)WebRequest.Create("https://www.example.com/response");
request.Method = "GET";
request.Accept = "application/json";
request.ContentType = "application/json; charset=utf-8;"
var response = (HttpWebResponse)request.GetResponse();
var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
dynamic data = JOBject.Parse(response);
Console.WriteLine(data.name);
Example of response in full -
[{"_id":"hello","_source":{"name":"hello","example":"hey"},"_type":"_doc"}]
Try This:
WebRequest webRequest = WebRequest.Create("https://www.example.com/response");
HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();
if (response.StatusDescription == "OK")
{
Stream dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
string responseFromServer = reader.ReadToEnd();
// Display the content.
dynamic data = JObject.Parse(responseFromServer);
Console.Write(data.name);
}
You can create these two classes like this.
public class Source
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("example")]
public string Example { get; set; }
}
public class ResponseObject
{
[JsonProperty("_id")]
public string Id { get; set; }
[JsonProperty("_source")]
public Source Source { get; set; }
[JsonProperty("_type")]
public string Type { get; set; }
}
And then parse your response like this
var data = JsonConvert.DeserializeObject<ResponseObject>(response);
Hope this will help you

Put a part of a POST request in variable

I did a POST request code pointing to an API to do an automatic exchange program.
Here is the code:
string webAddr = "https://shapeshift.io/shift";
var httpWebRequest = (HttpWebRequest)WebRequest.Create(webAddr);
httpWebRequest.ContentType = "application/json; charset=utf-8";
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = "{ \"withdrawal\" : \"***ADDRESS WITH LETTER AND NUMBER***\", \"pair\" : \"eth_xmr\" }";
streamWriter.Write(json);
streamWriter.Flush();
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var responseText = streamReader.ReadToEnd();
Console.WriteLine(responseText);
}
And after executing the code, I'm getting this in the console
{"orderId":"1f90346c-c6d4-4d89-a24c-78b2bbdb6292","deposit":"0x534aa684274b4711f65b2d0e2e403cb169201255","depositType":"ETH","withdrawal":"***ADDRESS WITH LETTER AND NUMBER***","withdrawalType":"XMR"
Now, I want to put the address from deposit that I'm getting from the API into a string variable. I tried some code but I can't make it working. So how can I put this address in a string variable ?
You could deserialize the response and get from there that you want. In order to do so you could define a class, let's name it ApiResponse:
public class ApiResponse
{
[JsonProperty("orderId")]
public string orderId { get; set; }
[JsonProperty("deposit")]
public string deposit { get; set; }
[JsonProperty("depositType")]
public string depositType { get; set; }
[JsonProperty("withdrawal")]
public string withdrawal { get; set; }
[JsonProperty("withdrawalType")]
public string withdrawalType { get; set; }
}
and then after
var responseText = streamReader.ReadToEnd();
make the deserialization:
var apiResponse = JsonConvert.DeserializeObject<ApiResponse>(responseText);
I have used the Json.NET library. So if you haven't isntall it, you should do so or you could make use of another library and change correspondingly the above code.

How to parse Json WebApi response containing C# list

hi I have a json response like
{"Status":"Success","Message":"Authentication
successful","Data":{"Key":"sdsdIRs99Iebe6QHmawlBsCks9mqfUt6jKYNQ%2bW","UserId":"ddjjj8-11e6-637af7"}}
how can I parse this to read response.
I am doing this way:
private void POST(string url)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
postData="{\"UserName\": \"abc\"," +"\"Password\": \"mypwd\"}";
Byte[] byteArray = Encoding.UTF8.GetBytes(postData);
request.ContentLength = byteArray.Length;
request.ContentType = #"application/x-www-form-urlencoded";
using (Stream dataStream = request.GetRequestStream())
{
dataStream.Write(byteArray, 0, byteArray.Length);
}
long length = 0;
try
{
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
length = response.ContentLength;
using (var reader = new StreamReader(response.GetResponseStream()))
{
JavaScriptSerializer js = new JavaScriptSerializer();
var objText = reader.ReadToEnd();
string str= objText;
MyObject myojb = (MyObject)js.Deserialize(objText,typeof(MyObject));
}
}
}
catch (WebException ex)
{
// Log exception and throw as for GET example above
}
}
I am able to read "Status" and "Message" but unable to read "Key" and "UserID" values.
Please help!
You can use Newtonsoft Json instead of JavaScriptSerializer the class structure for your json looks like this
public class Rootobject
{
public string Status { get; set; }
public string Message { get; set; }
public Data Data { get; set; }
}
public class Data
{
public string Key { get; set; }
public string UserId { get; set; }
}
Deserialization could be done easily like
Rootobject ro = JsonConvert.DeserializeObject<Rootobject>(json);
Console.WriteLine(ro.Status + ", " + ro.Message + ", " + ro.Data.Key + ", " + ro.Data.UserId);
Guessing (since we don't know the structure of the MyObject class) how you access your data:
String status = myobj.status;
String message = myobj.message;
Now since the other data properties are in the "data" node of your json, you should be able to access them like this:
String key = myobj.data.key;
String userId = myobj.data.userId;

Sending a class object with Stream property using Rest

I can send a simple class object with some properties like this:
[DataContract]
public class DeviceInfo
{
[DataMember]
public string DeviceCode { get; set; }
[DataMember]
public string ClientKey { get; set; }
[DataMember]
[XmlIgnore]
public DateTime Timestamp { get; set; }
[DataMember]
public string Token { get; set; }
}
WindowsForm code:
string baseAddress = "http://some_webservice_url";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(baseAddress);
request.Method = "POST";
request.ContentType = "application/json";
DeviceInfo customData = new DeviceInfo();
customData.DeviceCode = "123456";
customData.ClientKey = "hfhf8djf89dfk9";
customData.Timestamp = "12-12-2013";
customData.Token = "444sdf54df544r";
byte[] byteArray = Encoding.UTF8.GetBytes(Serialize<DeviceInfo>(customData));
request.ContentLength = byteArray.Length;
Stream dataStream = request.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
MessageBox.Show(Utility.ReadResponse(response));
}
// SERIALIZATION PART
public static string Serialize<T>(T obj)
{
System.Runtime.Serialization.Json.DataContractJsonSerializer serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(obj.GetType());
MemoryStream ms = new MemoryStream();
serializer.WriteObject(ms, obj);
string retVal = Encoding.Default.GetString(ms.ToArray());
ms.Dispose();
return retVal;
}
public static byte[] ReadFully(Stream input)
{
byte[] buffer = new byte[16 * 1024];
using (MemoryStream ms = new MemoryStream())
{
if (input != null)
{
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
}
return ms.ToArray();
}
}
What it does is sending DeviceInfo to the server.
But how could I do this using a class object with Stream property:
public class PhotoData
{
public string ProductId { get; set; }
public string PhotoId { get; set; }
public System.IO.Stream FileData { get; set; }
}
This is what I have done so far and it is throwing an error, saying
Type 'System.IO.FileStream' with data contract name 'FileStream:http://schemas.datacontract.org/2004/07/System.IO'
is not expected. Consider using a DataContractResolver or add any types not known statically to the list of
known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types
passed to DataContractSerializer.
StreamReader sr = new StreamReader(openFileDialog1.FileName);
byte[] fileStream = ReadFully(sr.BaseStream);
PhotoData pd = new PhotoData();
pd.FileData = sr.BaseStream;
pd.ProductId = "121513542454545";
pd.PhotoId = textBox4.Text;
baseAddress = "http://someurl/rest/UploadPhotoStream";
request = (HttpWebRequest)WebRequest.Create(new Uri(baseAddress));
request.Method = "POST";
request.ContentType = "application/octet-stream";
byteArray = Encoding.UTF8.GetBytes(Serialize<PhotoData>(pd));
request.ContentLength = byteArray.Length;
Stream dataStream2 = request.GetRequestStream();
dataStream2.Write(byteArray, 0, byteArray.Length);
dataStream2.Close();
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
MessageBox.Show(Utility.ReadResponse(response));
}
I recommend using a byte[] instead of a Stream.
public class PhotoData
{
public string ProductId { get; set; }
public string PhotoId { get; set; }
public byte[] FileData { get; set; }
}
Then you can read/write to the FileData using a MemoryStream in the conventional way. I'm not entirely sure what your method is attempting to do, but I think it would end up looking a bit like this:
byte[] fileStream = ReadFully(sr.BaseStream);
PhotoData pd = new PhotoData();
pd.FileData = fileStream;

Categories