C# - JSON serialization for SNS - c#

I want to serialize a message to be sent through AWS SNS module.
public async Task<string> jsonConvert(string message)
{
datamessage datamessage = new datamessage { message = message };
gcmMessage lGcm = new gcmMessage { data = datamessage };
MessageDto messageDto = new MessageDto { GCM = JsonConvert.SerializeObject(lGcm) };
var msg = JsonConvert.SerializeObject(messageDto);
return msg;
}
I'm using this code for the same but the return value is
{"GCM":"{\"data\":{\"message\":\"TestMsg\"}}"}
But I want it as
{"default": "TestMsg", "GCM": "{ \"data\": { \"message\": \"TestMsg\" } }"}
Any help would be appreciated.

The structure for the Json you want tot create should look like this:
Classes:
public class Data
{
[JsonProperty("message")]
public string Message { get; set; }
}
public class GCM
{
[JsonProperty("data")]
public Data Data { get; set; }
}
public class RootObject
{
[JsonProperty("default")]
public string Default { get; set; }
[JsonProperty("GCM")]
public GCM GCM { get; set; }
}
Create the message:
RootObject rootObject = new RootObject
{
Default = "TestMsg",
GCM = new GCM { Data = new Data { Message = "TestMsg" } }
};
Serialize:
var serialized = JsonConvert.SerializeObject(rootObject);
Result
"{\"default\":\"TestMsg\",\"GCM\":{\"data\":{\"message\":\"TestMsg\"}}}"
In your method it would look like this:
public async Task<string> jsonConvert(string message)
{
RootObject rootObject = new RootObject
{
Default = message,
GCM = new GCM { Data = new Data { Message = message } }
};
var msg = await Task.Factory.StartNew(() => JsonConvert.SerializeObject(rootObject));
return msg;
}

Related

How can we deserialize JSON data to c# object from API response

I need to deserialize my json data. I am using Newtonsoft.Json for json operations. I tried a lot of method to deserialize this data but i failed. Btw, I need to summarize my system for better understanding. I am posting data every minute to an API. And its response to me. So I am trying to deserialize the response.
What need I do to deserialize this json and use it like a normal c# object? I want to deserialize res variable. Thank you for your interest.
Here is the main code
var data = new SendData
{
Readtime = time,
Stationid = new Guid(_stationid),
SoftwareVersion = softwareVersion,
Period = period,
AkisHizi = akisHizi,
AkisHizi_Status = status,
AKM = akm,
AKM_Status = status,
CozunmusOksijen = cozunmusOksijen,
CozunmusOksijen_Status = status,
Debi = debi,
Debi_Status = status,
DesarjDebi = desarjDebi,
DesarjDebi_Status = status,
KOi = koi,
KOi_Status = status,
pH = ph,
pH_Status = status,
Sicaklik = sicaklik,
Sicaklik_Status = status,
Iletkenlik = iletkenlik,
Iletkenlik_Status = status
};
var res = Services.sendData(data);
MessageBox.Show(res.objects.ToString());
Here is the services model PostData method
private ResultStatus<T> PostData<T>(string url, string data) where T : new()
{
try
{
using (var webClient = new WebClient())
{
webClient.Encoding = Encoding.UTF8;
webClient.Headers.Add("AToken", JsonConvert.SerializeObject(new AToken { TicketId = this.TicketId.ToString() }));
var resp = webClient.UploadString(this.Url + url, data);
return JsonConvert.DeserializeObject<ResultStatus<T>>(resp);
}
}
catch (Exception ex)
{
return new ResultStatus<T>
{
message = ex.Message + System.Environment.NewLine + url
};
}
}
Here is the sendData method
public ResultStatus<object> sendData(SendData data)
{
var res = PostData<object>(this.stationType.ToString() + "/SendData", JsonConvert.SerializeObject(data));
return res;
}
Here is the MessageBox result (json data)
{
'Period': 1,
'ReadTime':
'2022-08-22714:01:00',
'AKM': 65.73,
'AKM_Status': 1,
'CozunmusOksijen': 0.2,
'CozunmusOksijen_Status': 1,
'Debi': 1.0,
'Debi_Status': 1,
'KOi': 25.1,
'KOi_Status': 1
}
Your JSON is probably,
{
"Period": 1,
"ReadTime": "2022-08-22T14:01:00",
"AKM": 65.73,
"AKM_Status": 1,
"CozunmusOksijen": 0.2,
"CozunmusOksijen_Status": 1,
"Debi2": 1.0,
"Debi_Status": 1,
"KOi": 25.1,
"KOi_Status": 1
}
From https://app.quicktype.io/, a C# model would be,
// <auto-generated />
//
// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:
//
// using QuickType;
//
// var thing = Thing.FromJson(jsonString);
namespace QuickType
{
using System;
using System.Collections.Generic;
using System.Globalization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
public partial class Thing
{
[JsonProperty("Period")]
public long Period { get; set; }
[JsonProperty("ReadTime")]
public DateTimeOffset ReadTime { get; set; }
[JsonProperty("AKM")]
public double Akm { get; set; }
[JsonProperty("AKM_Status")]
public long AkmStatus { get; set; }
[JsonProperty("CozunmusOksijen")]
public double CozunmusOksijen { get; set; }
[JsonProperty("CozunmusOksijen_Status")]
public long CozunmusOksijenStatus { get; set; }
[JsonProperty("Debi2")]
public long Debi2 { get; set; }
[JsonProperty("Debi_Status")]
public long DebiStatus { get; set; }
[JsonProperty("KOi")]
public double KOi { get; set; }
[JsonProperty("KOi_Status")]
public long KOiStatus { get; set; }
}
public partial class Thing
{
public static Thing FromJson(string json) => JsonConvert.DeserializeObject<Thing>(json, QuickType.Converter.Settings);
}
public static class Serialize
{
public static string ToJson(this Thing self) => JsonConvert.SerializeObject(self, QuickType.Converter.Settings);
}
internal static class Converter
{
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
{
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
DateParseHandling = DateParseHandling.None,
Converters =
{
new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
},
};
}
}
As per https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-how-to?pivots=dotnet-6-0#how-to-read-json-as-net-objects-deserialize
Thing? thing = JsonSerializer.Deserialize<Thing>(res);

Cannot deserialize the current JSON object into type 'System.Collections.Generic.List1' in Xamarin Forms

I'm having an error in Xamarin Forms I tried to deserialize the object does anyone know What did I do wrong here?
This is my method
private async void GetEmployee()
{
var _token = await GetAccessToken();
//List<D365Employee> Employee = null;
using (var _clientD365 = new HttpClient())
{
var _uri = "domain here";
_client.BaseAddress = new Uri(_uri);
_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _token);
var _response = await _clientD365.GetAsync("my endpoint here");
var Emp = JsonConvert.DeserializeObject<List<Employee>>(_response.Content.ReadAsStringAsync().Result);
Employee = new ObservableCollection<Employee>(Emp);
}
}
This is my Model
public class Employee
{
[JsonProperty("#odata.etag")]
public string Context { get; set; }
public IList<EmployeeDetails> Value { get; set; }
}
public class EmployeeDetails
{
public string PersonnelNumber { get; set; }
public string EmploymentLegalEntityId { get; set; }
public string DimensionDisplayValue { get; set; }
}
This is the JSON I try to parse
{
"#odata.context": "https://employee.dynamics.com/data/$metadata#Employees(PersonnelNumber,EmploymentLegalEntityId,DimensionDisplayValue)",
"value": [
{
"#odata.etag": "W/\"JzEsNTYzNzE0NDYwMzsxNDg2NTk2NzY0LDU2MzcxNDc2OTM7MSw1NjM3MTQ0NjAzOzEsNTYzNzE0NDYwMzsxLDU2MzcxNDczNzE7MCwwOzAsMDsyNTY0OTEwODksNTYzwJw==\"",
"PersonnelNumber": "ID111028",
"EmploymentLegalEntityId": "OOP",
"DimensionDisplayValue": "----",
}
]
}
That JSON is a single object, not a list, so you need to deserialize it as a single object.
var Emp = JsonConvert.DeserializeObject<Employee>(await _response.Content.ReadAsStringAsync());

How to send a message to a user with the same attachments that he sent me using VkNet?

I get a message from a user in a chatbot that contains an attachment in the form of a document. I need to identify this document, convert it and send it back. But first, I just need to send the same document to the sender. How can i do this?
var msg = Message.FromJson(new VkResponse(updates.Object));
try
{
if (msg.Attachments.Count > 0)
{
//
var attachment = msg.Attachments.First();
//
if (attachment.Type == typeof(Document))
{
var doc = attachment.Instance as Document;
var attachments = new List<MediaAttachment>{doc};
//attachments.Add(attachment);
_vkApi.Messages.Send(new MessagesSendParams
{
RandomId = new DateTime().Millisecond,
PeerId = msg.PeerId.Value,
Message = "true",
Attachments = attachments
});
return Ok("ok");
}
else
{
_vkApi.Messages.Send(new MessagesSendParams
{
RandomId = new DateTime().Millisecond,
PeerId = msg.PeerId.Value,
Message = "false"
});
return Ok("ok");
}
}
}
Class Updates.cs:
[Serializable]
public sealed class Updates
{
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("object")]
public JObject Object { get; set; }
[JsonProperty("group_id")]
public long GroupId { get; set; }
}

JSON Object and Simple Type to Model in WebAPI using FromBody

I am creating a Web Api method that should accept a JSON Object and a Simple Type. But all parameters are always null.
My json looks like
{
"oldCredentials" : {
"UserName" : "user",
"PasswordHash" : "myCHqkiIAnybMPLzz3pg+GLQ8kM=",
"Nonce" : "/SeVX599/KjPX/J+JvX3/xE/44g=",
"Language" : null,
"SaveCredentials" : false
},
"newPassword" : "asdf"}
And my Code looks like:
[HttpPut("UpdatePassword")]
[Route("WebServices/UsersService.svc/rest/users/user")]
public void UpdatePassword([FromBody]LoginData oldCredentials, [FromBody]string newPassword)
{
NonceService.ValidateNonce(oldCredentials.Nonce);
var users = UserStore.Load();
var theUser = GetUser(oldCredentials.UserName, users);
if (!UserStore.AuthenticateUser(oldCredentials, theUser))
{
FailIncorrectPassword();
}
var iv = Encoder.GetRandomNumber(16);
theUser.EncryptedPassword = Encoder.Encrypt(newPassword, iv);
theUser.InitializationVektor = iv;
UserStore.Save(users);
}
The current JSON you are sending maps to the following classes
public class LoginData {
public string UserName { get; set; }
public string PasswordHash { get; set; }
public string Nonce { get; set; }
public string Language { get; set; }
public bool SaveCredentials { get; set; }
}
public class UpdateModel {
public LoginData oldCredentials { get; set; }
public string newPassword { get; set; }
}
[FromBody] can only be used once in action parameters
[HttpPut("WebServices/UsersService.svc/rest/users/user")]
public void UpdatePassword([FromBody]UpdateModel model) {
LoginData oldCredentials = model.oldCredentials;
string newPassword = model.newPassword;
NonceService.ValidateNonce(oldCredentials.Nonce);
var users = UserStore.Load();
var theUser = GetUser(oldCredentials.UserName, users);
if (!UserStore.AuthenticateUser(oldCredentials, theUser)) {
FailIncorrectPassword();
}
var iv = Encoder.GetRandomNumber(16);
theUser.EncryptedPassword = Encoder.Encrypt(newPassword, iv);
theUser.InitializationVektor = iv;
UserStore.Save(users);
}
As per the Parameter Binding in ASP.NET Web API, "At most one parameter is allowed to read from the message body". Means only one parameter can contain [FromBody]. So in this case it will not work. Create one complex object and add required properties to it. You can add newPassword to your complex object to make it work.
More than one [FromBody] does not work in Api. Check this Microsoft Official blog
So now you can do like this, create a complex object which should contain both your oldCredentials and newPassword. For example LoginData class in my example bellow. And myLoginRequest is another object class which is to deserialized your LoginData.
[HttpPut("UpdatePassword")]
[Route("WebServices/UsersService.svc/rest/users/user")]
public void UpdatePassword([FromBody]LoginData MyCredentials)
{
loginRequest request = JsonConvert.DeserializeObject<myLoginRequest>
(json.ToString());
// then you can do the rest
public class DocumentController : ApiController
{
[HttpPost]
public IHttpActionResult PostDocument([FromBody] Container data)
{
try
{
if (string.IsNullOrWhiteSpace(data.Document)) return ResponseMessage(Request.CreateResponse(HttpStatusCode.NoContent, "No document attached"));
return ResponseMessage(IndexDocument(data, Request));
}
catch (Exception ex)
{
return ResponseMessage(Request.CreateResponse(HttpStatusCode.NotAcceptable, ex.Message));
}
}
}
public class InsuranceContainer
{
[JsonProperty("token")]
public string Token { get; set; }
[JsonProperty("document")]
public string Document { get; set; }
[JsonProperty("text")]
public string Text { get; set; }
}
var fileAsBytes = File.ReadAllBytes(#"C:\temp\tmp62.pdf");
String asBase64String = Convert.ToBase64String(fileAsBytes);
var newModel = new InsuranceContainer
{
Document = asBase64String,
Text = "Test document",
};
string json = JsonConvert.SerializeObject(newModel);
using (var stringContent = new StringContent(json, System.Text.Encoding.UTF8, "application/json"))
using (var client = new HttpClient())
{
var response = await client.PostAsync("https://www.mysite.dk/WebService/api/Document/PostDocument", stringContent);
Console.WriteLine(response.StatusCode);
var message = response.Content.ReadAsStringAsync();
Console.WriteLine(message.Result);
}

Part of object that is returned is null

I have the following method in my web api controller
public HttpResponseMessage PostGrantAccess(DeviceAccessRequest deviceAccessRequest)
{
var deviceId = deviceAccessRequest.DeviceId;
var deviceAccessResponse = new DeviceAccessResponse(deviceAccessRequest.RequestId)
{
Status = "OK"
};
var response = Request.CreateResponse<DeviceAccessResponse>(HttpStatusCode.OK, deviceAccessResponse);
return response;
}
This is the calling client code:
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:55208/");
var request = new DeviceAccessRequest
{
RequestId = Guid.NewGuid().ToString(),
DeviceId = "bla",
LoginId = "tester",
Password = "haha" ,
};
var response = client.PostAsJsonAsync("api/accesspanel", request).Result;
if (response.IsSuccessStatusCode)
{
var deviceAccessResponse = response.Content.ReadAsAsync<DeviceAccessResponse>().Result;
}
}
Object classes:
public class DeviceAccessResponse : ResponseBase
{
public DeviceAccessResponse()
{
}
public DeviceAccessResponse(string correlationId)
: base(correlationId)
{
}
public string Status { get; set; }
}
public class ResponseBase
{
private string correlationId;
public ResponseBase()
{
}
public ResponseBase(string correlationId)
{
this.correlationId = correlationId;
}
}
I am able to receive DeviceAccessRequest in my controller just fine, I am able to get the guid string.
However, after returning the response back to the client, I am only able to get back Status = "OK", the correlationId is null instead of containing the guid string which I have assigned in the client code with this line
var deviceAccessResponse = new DeviceAccessResponse(deviceAccessRequest.RequestId)
What did I miss?
is the response.Content.ReadAsAsync<DeviceAccessResponse>().Result; the correct code to use to reconstruct my whole object?
Your correlationId is a private field. If you want it to serialize over the wire, you probably need to make a public property to expose it.
You should make the correlationId a public property if you want it to be exposed and travel to the client:
public class ResponseBase
{
public ResponseBase()
{
}
public string CorrelationId { get; set; }
public ResponseBase(string correlationId)
{
this.CorrelationId = correlationId;
}
}

Categories