I am creating a webservice to interact with a JSON API.
This API needs me to set a root element in the string, but I just cannot get this to happen.
The place where it all happens - right now just made to just show me the json output:
public static string CreateServiceChange(ServiceChange change)
{
string json = JsonConvert.SerializeObject(change);
return json;
}
This is the ServiceChange class:
public class ServiceChange
{
[JsonProperty("email")]
public string requesterEmail { get; set; }
[JsonProperty("description_html")]
public string descriptionHtml { get; set; }
[JsonProperty("subject")]
public string subject { get; set; }
[JsonProperty("change_type")]
public int changeType { get; set; }
}
And the method binding those two together:
public string copyTicketToChange(int ticketId)
{
HelpdeskTicket.TicketResponseActual ticket = getHelpdeskTicket(ticketId);
ServiceChange change = new ServiceChange();
change.descriptionHtml = ticket.Response.DescriptionHtml;
change.requesterEmail = ticket.Response.Email;
change.subject = ticket.Response.Subject;
change.changeType = 1;
string Response = Dal.CreateServiceChange(change);
return Response;
}
The json output looks like this right now:
{"email":"test#test.com","description_html":"This is a test","subject":"Testing","change_type":1}
And the expected output:
{ "itil_change": {"email":"test#test.com","description_html":"This is a test","subject":"Testing","change_type":1}}
How can I achieve this?
Wrap your ServiceChange into another object and serialize it:
public class ServiceChangeWrapper
{
public ServiceChange itil_change { get; set; }
}
...
public static string CreateServiceChange(ServiceChange change)
{
ServiceChangeWrapper wrapper = new ServiceChangeWrapper { itil_change = change};
string json = JsonConvert.SerializeObject(wrapper);
return json;
}
Related
On my API side, I use JsonConvert.SerializeObject() to set it to a string. This is the output from my API:
{"ContentType":null,"SerializerSettings":null,"StatusCode":null,"Value":{"draw":1,"recordsTotal":0,"recordsFiltered":0,"data":[],"order":null,"orderdir":null}}
This is what the API looks like:
[HttpPost("Preview")]
public JsonResult Preview([FromBody]AnnouncementAccessPreviewRequestViewModel svm)
{
ApiResponseViewModel arvm = new ApiResponseViewModel();
var res = announcementData.Preview(svm.SearchViewModel, svm.TenantId);
arvm.IsSuccessful = true;
arvm.Message = null;
arvm.Output = JsonConvert.SerializeObject(res);
return Json(arvm);
}
arvm.Output is a string
How can I only take the Value section from the output?
That's how I solved it when I had this problem.
private YourModel GetJsonObject()
var parsedObject = JObject.Parse(resultContent);
string p = parsedObject.ToString();
if (p.Contains("Succes"))
{
string popupJson = JObject.Parse(parsedObject["data"].ToString()).ToString();
YourModel= JsonConvert.DeserializeObject<YourModel>(popupJson);
return YourModel;
}
There is a side way to get this model from https://json2csharp.com/.
you can try this
var output=JObject.Parse(json);
Value value=output["Value"].ToObject<Value>();
class
public class Value
{
public int draw { get; set; }
public int recordsTotal { get; set; }
public int recordsFiltered { get; set; }
public List<object> data { get; set; }
public object order { get; set; }
public string orderdir { get; set; }
}
or if you can change Api
public JsonResult Preview([FromBody]AnnouncementAccessPreviewRequestViewModel svm)
{
var res = announcementData.Preview(svm.SearchViewModel, svm.TenantId);
var output = JsonConvert.SerializeObject(res);
return Json(output);
}
but the right way is
public IActionResult Preview([FromBody]AnnouncementAccessPreviewRequestViewModel svm)
{
return announcementData.Preview(svm.SearchViewModel, svm.TenantId);
}
in this case you don't need to serialize or deserialize
Hello I have problem with deserializing IRestResponse.Content JSON response.
{
"49":
{
"9345": "2018-10-11",
"106": null,
"107": "4222238842",
"108": "CompanyName",
"8210": "2018-11-11/1",
"110": "00-300",
"109": "Street",
"112": "Country",
"18418": null,
"18420": "S\u0141ON",
"18422": "OtherString",
"9338": null,
"111": "City"
}
}
I have tried some webpage's or built in VisualStudio converter but It gives my something like this.
public class Rootobject
{
public _49 _49 { get; set; }
}
public class _49
{
public string _9345 { get; set; }
public object _106 { get; set; }
public string _107 { get; set; }
public string _108 { get; set; }
public string _8210 { get; set; }
public string _110 { get; set; }
public string _109 { get; set; }
public string _112 { get; set; }
public object _18418 { get; set; }
public string _18420 { get; set; }
public string _18422 { get; set; }
public object _9338 { get; set; }
public string _111 { get; set; }
}
This look's ok but In my case those JSON files have dynamic property names and can have another "int" values. Also the nested content inside "49" can have less or more values.
I am especially interested in gathering "49" << this value to variable.
I also have tried something like this, but doesn't work either:
public class DeserializeJsonContent
{
public Dictionary<object, Dictionary<object, object>> values { get; set; }
}
Simplified code sample
public List<T> JSONDeserialize<T>(IRestResponse response) where T : new()
{
var responseData = client.Deserialize<List<T>>(response);
var ListDeserializedData = responseData.Data.ToList<T>();
return ListDeserializedData;
}
....
var response = rest.client.Execute(request);
if (response.IsSuccessful)
{
var obj = rest.JSONDeserialize<DeserializeJsonContent>(response);
}
obj has count 1 but vals = null
Edit after Solve:
I still have no idea why my deserialized class doesn't work in this case (I am using it in many other json deserialization response's)
Thanks to xdtTransform answer I have tried and all of those worked
var obj2 = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<object, object>>>(response.Content);
var obj3 = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, string>>>(response.Content);
var obj4 = JsonConvert.DeserializeObject<Dictionary<int, Dictionary<string, string>>>(response.Content);
var obj5 = JsonConvert.DeserializeObject<Dictionary<object, Dictionary<string, string>>>(response.Content);
var obj6 = JsonConvert.DeserializeObject<Dictionary<object, Dictionary<object, object>>>(response.Content);
var obj7 = JsonConvert.DeserializeObject<Dictionary<object, Dictionary<int, object>>>(response.Content);
Then just
var value = obj2.First().Key;
Using Newtonsoft.Json, You can directly deserialize to Dictionary<string,Dictionary<string,string>> like :
var obj = JsonConvert.DeserializeObject<Dictionary<string,Dictionary<string,string>>>(input);
If you need it to be in your custom type, you should declare this type like :
public class WrapperType : Dictionary<string,Dictionary<string,string>>{}
Then the Deserialisation stay the same:
var obj = JsonConvert.DeserializeObject<WrapperType>(input);
Updated demo
Please deserialize response content
string data = response.Content;
var responseData = client.Deserialize<List<T>>(data);
I have this response from server
[{
"sys_id": "******************************",
"dv_model_id": "*****************",
"due": "YYYY-MM-DD HH:mm:ss",
"assigned_to": "1524s32a54dss412s121s",
"dv_assigned_to": "username",
"assigned_to.phone": "+12345678910",
"assigned_to.email": "abc#a.c",
"u_borrower_id": "fb36e45f0a12452004742183457e833b0",
"dv_u_borrower_id": "antoherUserName",
"u_borrower_id.phone": "+12345678910",
"u_borrower_id.email": "abcf#a.c"
}
,{....}
,{....}]
I'm trying to deserialize this to List
public class Inventory
{
public Inventory()
{
assigned_to = new User();
u_borrower_wwid = new User();
}
public string sys_ID { get; set; }
public string dv_model_id { get; set; }
public DateTime due { get; set; }
public string dv_assigned_to { get; set; }
public User assigned_to { get; set; }
public string dv_u_borrower_id { get; set; }
public User u_borrower_id { get; set; }
}
now, since the JSON contains - "assigned_to": "1524s32a54dss412s121s","
the deserialization failed.
the same with the - ""u_borrower_id": "fb36e45f0a12452004742183457e833b0"," .
do you know any way to ignore them? or remove them from the JSON?
I need only the properties (".phone" and ".email") of the object.
any ideas?
I see a number of solutions:
Modify your Inventory object (or create a new one) so the json can be fully deserialized, then access the values there.
Your new and updated object should look like this:
public class InventoryJsonObject
{
public string sys_id { get; set; }
public string dv_model_id { get; set; }
public string due { get; set; }
public string assigned_to { get; set; }
public string dv_assigned_to { get; set; }
[JsonProperty("assigned_to.phone")]
public string assigned_to_phone { get; set; }
[JsonProperty("assigned_to.email")]
public string assigned_to_email { get; set; }
public string u_borrower_id { get; set; }
public string dv_u_borrower_id { get; set; }
[JsonProperty("u_borrower_id.phone")]
public string u_borrower_id_phone { get; set; }
[JsonProperty("u_borrower_id.email")]
public string u_borrower_id_email { get; set; }
}
Use regular expressions to get the values from the string. In this case your regex would be "u_borrower_id\.phone": "(.*?)" and "u_borrower_id\.email": "(.*?)"
The complete regex solution could look like this (assuming every object has a phone and email included):
string phonePattern = "\"u_borrower_id\\.phone\": \"(.*?)\"";
string emailPattern = "\"u_borrower_id\\.email\": \"(.*?)\"";
Regex phoneRegex = new Regex(phonePattern);
var phoneMatches = phoneRegex.Matches(input);
Regex emailRegex = new Regex(emailPattern);
var emailMatches = emailRegex.Matches(input);
for (int i = 0; i < phoneMatches.Count; i++)
{
string phoneMatch = phoneMatches[i].Groups[1].Value;
string emailMatch = emailMatches[i].Groups[1].Value;
// Now you can add them to any collection you desire
}
Implement a cast between string and User. Since your error originates from the fact that the string fb36e45f0a12452004742183457e833b0 cannot be cast into a User object trivially, you have to implement the cast. It would look like this:
public static implicit operator User(string _string)
{
// This could be a DB lookup, or basically anything else
return new User()
{
id = _string
};
}
In order to avoid unnecessary casting that causes bug you can use this workaround by creating a Dictionary<string, object>
and read only the properties you need as strings and convert them to your desired type:
using System.Web.Script;
Dictionary<string, object> dict = Serialization.JavaScriptSerializer().Deserialize<Dictionary<string, object>>(json);
Now you can modify your class properties one by one like:
(You can create additional method for your DateTime and User property)
Inventory inventory = new Inventory();
//notice i'v added the 'u_borrower_id_email' property to your class:
inventory.u_borrower_id_email = dict.GetStringOrDefault("u_borrower_id.phone");
private static string GetStringOrDefault(this Dictionary<string, object> data, string key)
{
string result = "";
object o;
if (data.TryGetValue(key, out o))
{
if (o != null)
{
result = o.ToString();
}
}
return result;
}
My Service returns a JSON like below, I want to Parse this and bind category_name to my list, how to do this in C#, UWP apps.
Iam trying to Deserialize this in this way
var content_resp = await response.Content.ReadAsStringAsync();
content_resp = "{ \"root\": " + content_resp.Trim().TrimStart('{').TrimEnd('}') + " }";
var xmlProducts = JsonConvert.DeserializeXNode(content_resp);
var xmlProductNodes = xmlProducts.DescendantNodes();
foreach (XElement xmlProduct in xmlProductNodes)
{
Places pl = new Places();
var node = xmlProducts.Element("category_parent").Value;
pl.category_name = xmlProducts.Element("category_name").Value;
}
}
catch (Exception ex)
{
//throw or return an appropriate response/exception
}
when the debuger comes at this line
var xmlProducts = JsonConvert.DeserializeXNode(content_resp);
it is giving an error like
"This operation would create an incorrectly structured document."
The easiest way that I have found is to use Newtonsoft.Json
Firstly you should create class with data equal to your JSON:
public class AppsData
{
private string _category_id;
private string _category_name;
public string category_id
{
get { return _category_id; }
set { _category_id = value; }
}
public string category_name
{
get { return _category_name; }
set { _category_name = value; }
}
}
Then you can create some helper class:
static class JSONhelper
{
public static IList<T> DeserializeToList<T>(string jsonString)
{
var array = Newtonsoft.Json.Linq.JArray.Parse(jsonString);
IList<T> objectsList = new List<T>();
foreach (var item in array)
{
try
{
objectsList.Add(item.ToObject<T>());
}
catch { }
}
return objectsList;
}
}
Then create instance of List
IList<AppsData> appsdata;
and try to deserialize:
appsdata = JSONhelper.DeserializeToList<AppsData>(stringWithJSON);
If there is no reason to deserialize to XML you can do the following:
Create the class to parse
public class Product
{
public string category_id { get; set; }
[JsonProperty("0")]
public string Zero { get; set; }
public string category_name { get; set; }
[JsonProperty("1")]
public string One { get; set; }
public string category_details { get; set; }
[JsonProperty("2")]
public string Two { get; set; }
public string category_link { get; set; }
[JsonProperty("3")]
public string Three { get; set; }
}
And then
var products = JsonConvert.DeserializeObject<IList<Product>>(your json);
Trying to get the result from a webservice call to return a Model. I eep getting the error:
Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'CI.Models.Schedule' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
public Schedule getCourseSchedule()
{
var obj = new
{
States = new[] { new { State = "MX" } },
Zip = "",
Miles = "",
PaginationStart = 1,
PaginationLimit = 3
};
using (var client = new WebClient())
{
client.Headers[HttpRequestHeader.ContentType] = "apoplication/json";
var url = "http://192.168.1.198:15014/ShoppingCart2/CourseSchedule";
var json = JsonConvert.SerializeObject(obj);
byte[] data = Encoding.UTF8.GetBytes(json);
byte[] result = client.UploadData(url, data);
string returnjson = Encoding.UTF8.GetString(result);
Schedule sched = JsonConvert.DeserializeObject<Schedule>(returnjson);
return sched;
}
}
Schedule Model:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Globalization;
namespace CI.Models
{
public class Schedule
{
public IEnumerable<Course> Courses { get; set; }
}
public class Course
{
/*
JSON Data returned from web service:
{
"ProgramGroup":"MR",
"ProgramCode":"RM",
"EventCode":"20160901MXMR",
"FormalDate":"September 1-2, 2016",
"StartDate":"2016\/09\/01",
"Price":5,
"LocName":"WB Hotel",
"LocAddress":"Av. Speedy Gonzales 220",
"LocCity":"Monterrey",
"LocState":"MX",
"LocZipCode":null,
"LicenseeURL":null,
"AgendaURL":"NA",
"SeatsAreAvailable":"2",
"GeneralInfoHTML":"General Info goes here.",
"GateKeeperHTML":null,
"EventType":"SS",
"TotalCourses":3
}
*/
public string ProgramGroup { get; set; }
public string ProgramCode { get; set; }
public string EventCode { get; set; }
public string FormalDate { get { return FormalDate; } set { FormalDate = convertFormalDateToSpanish(value); } }
public string StartDate { get; set; }
public double Price { get; set; }
public string LocName { get; set; }
public string LocAddress { get; set; }
public string LocCity { get ; set; }
public string LocState { get; set; }
public string LocZipCode { get; set; }
public string LicenseeURL { get; set; }
public string AgendaURL { get { return AgendaURL; } set { AgendaURL = buildAgendaLink(value); } }
public string SeatsAreAvailable { get; set; }
public string GeneralInfoHTML { get; set; }
public string GateKeeperHTML { get; set; }
public string EventType { get; set; }
public int TotalCourses { get; set; }
public string convertFormalDateToSpanish(string val)
{
DateTime TheDate = DateTime.Parse(StartDate);
string[] FormalDate = val.Split(" ".ToCharArray());
CultureInfo ci = new CultureInfo("es-ES");
string _Date = FormalDate[1].Replace("-", " al ").Replace(",", "");
string _Month = ci.TextInfo.ToTitleCase(TheDate.ToString("MMMM", ci));
val = string.Concat(_Date, " ", _Month);
return val;
}
private string buildAgendaLink(string val)
{
if (val.Trim() != "")
{
val = string.Concat("Agenda");
}
else
{
val = "Agenda";
}
return val;
}
}
}
Your server returns an array. Just try
Course[] courses = JsonConvert.DeserializeObject<Course[]>(returnjson);
Note that this is not an answer to your original problem, but I added it like an answer in order to explain my comment above with some actual code.
First problem with your code is that FormalDate and AgendaUrl properties simply won't work. Accessing them will result in a StackOverflowException, because you basically defined them recursively.
A property is merely syntax sugar for two separate getter/setter methods, so by writing this:
public class Course
{
public string FormalDate
{
get { return FormalDate; }
}
}
You are basically writing this:
public class Course
{
public string GetFormalDate()
{
// recursive call, with no terminating condition,
// will infinitely call itself until there is no
// more stack to store context data (and CLR
// will then throw an exception)
return GetFormalDate();
}
}
To fix that, you need to add an actual backing field, e.g.:
public class Course
{
private string _formalDate; // <-- this is a backing field;
// and this property uses the backing field to read/store data
public string FormalDate
{
get { return _formalDate; }
set { _formalDate = convertFormalDateToSpanish(value); }
}
}
Additionally, it's unusual for a property getter to return a different value than the one set through a setter. In other words, I would never expect this from a class:
var course = new Course();
course.StartDate = "2016/09/01";
course.FormalDate = "September 1-2, 2016";
Console.WriteLine(course.FormalDate); // prints "1 al 2 Septiembre" ?
I would rather move this functionality into a different class, or at least create different properties which return these values:
public class CourseInfo
{
// this is now a "dumb" auto-implemented property
// (no need for a backing field anymore)
public string FormalDate { get; set; }
// this read-only property returns the converted value
public string LocalizedFormalDate
{
get
{
return convertFormalDateToSpanish(FormalDate);
}
}
}