Cannot Parse Json sub object - asp.net

I am using JObject to parse Json object below
string Jstring = #"{
"PolicyId" :"xxxxxx",
"PolicyHolder" :{"title":"Mr", "FirstName":"test", "LastName":"testLast"}
}";
I can get the PolicyId value through below code
Jobject jobj = Jobject.parse(Jstring);
string PolicyId = jobj.value<string>("PolicyId");
But, I always get null using below code:
string Holder = jobj.value<string>("PolicyHolder");
I have debugged the code below:
jobj.Properties()
I can find PolicyHolder in the List. I have tried code below also, the value is always null
JProperty jproperty = jobj.Properties().SingleOrDefault(x => x.Name == "PolicyHolder");
Can anyone know what happen?

string Holder = jobj.value<string>("PolicyHolder");
Above line fails because PolicyHolder is not string. You are trying to cast it to string. It's an object. You must create a class with the properties of the PolicyHolder and use that as a type instead of string.

Here's the working dotNetFiddle: https://dotnetfiddle.net/xOOl5m
Console Output:
Here are the classes I ended up declaring and using.
public class PolicyHolder
{
public string title { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Policy
{
public string PolicyId { get; set; }
public PolicyHolder PolicyHolder { get; set; }
}
Like Sam has mentioned, PolicyHolder is an Object not a string.
Here's the complete code listing (so that the answer is self-contained).
using System;
using System.Linq;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
public class Program
{
// Solution to SO Question: https://stackoverflow.com/q/27159478/325521
// This Answer: https://stackoverflow.com/a/
// Author: Shiva Manjunath
// SO Profile: https://stackoverflow.com/users/325521/shiva
public static void Main()
{
string Jstring = #"{
""PolicyId"" :""xxxxxx"",
""PolicyHolder"" :{""title"":""Mr"", ""FirstName"":""test"", ""LastName"":""testLast""}
}";
JObject jObject = JObject.Parse(Jstring);
JProperty jProperty = jObject.Properties().SingleOrDefault(x => x.Name == "PolicyHolder");
Console.WriteLine("Printing Policy Holder Details....");
Console.WriteLine(jProperty.Value);
}
}
public class PolicyHolder
{
public string title { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Policy
{
public string PolicyId { get; set; }
public PolicyHolder PolicyHolder { get; set; }
}

Related

Deserialize JSON into List with X++

I have a problem with generic types in X++. I need to deserialize a JSON list yet everything I tried failed. Like using IEnumerables and JsonSerializer(does it find only AX classes and can't see references library classes?).
My helper class is in a C# library and I only need to get access to values inside the response JSON that are in list. How can I archive this in X++?
//X++
defaultException defaultException= new defaultException();
defaultException= JsonConvert::DeserializeObject(response, defaultException.GetType()); <- this gives is correct yet I cant use the values in the list
//values = FormJsonSerializer::deserializeCollection(classnum(List), response, Types::Class, 'defaultException');
// C#
public class defaultException
{
public MyException exception { get; set; }
}
public class MyException
{
public string serviceCtx { get; set; }
public string serviceCode { get; set; }
public string serviceName { get; set; }
public string timestamp { get; set;}
public string referenceNumber { get; set; }
public List<exceptionDetailList> exceptionDetailList { get; set; }
}
public class exceptionDetailList
{
public int exceptionCode { get; set; }
public string exceptionDescription { get; set; }
}
Found a solution. If we have another list in this list we need to recreate the enumerator in loop again and again as needed.
defaultException defaultException = new defaultException();
defaultException = JsonConvert::DeserializeObject(batch, defaultException.GetType());
System.Collections.IEnumerable exceptionList = defaultException.exception.exceptionDetailList;
System.Collections.IEnumerator enumerator = exceptionList.GetEnumerator();
while (enumerator.MoveNext())
{
exceptionDetailList exceptionDetailList = new exceptionDetailList();
exceptionDetailList = enumerator.Current;
}

how to resolve 'DataSet does not support System.Nullable<>.'?

My goal is to export data to a pdf file using crystal report and entity framework but unfortunately, I have been receiving this error message when I try to run my code.
'System.NotSupportedException: 'DataSet does not support System.Nullable<>.'
Can anyone please kindly assist me?
This is what I have tried so far on my controller side
using System.Data.Entity;
using System.IO;
using Final_INF271.Reports;
using CrystalDecisions.CrystalReports.Engine;
public ActionResult Export()
{
ReportDocument rd = new ReportDocument();
rd.Load(Path.Combine(Server.MapPath("~/Reports/OutstandingOrders.rpt")));
rd.SetDataSource(db.ProductOrder.Select(p => new
{
p.OrderID,
p.Date,
p.SupplierID,
p.CostPrice,
p.Quantity
}).ToList());
Response.Buffer = false;
Response.ClearContent();
Response.ClearHeaders();
Stream stream = rd.ExportToStream
(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat);
stream.Seek(0, SeekOrigin.Begin);
return File(stream, "application/pdf", "OutstandingOrders");
}
Included is my ProductOrder
namespace Final_INF271.Models
{
using System;
using System.Collections.Generic;
public partial class ProductOrder
{
public int OrderID { get; set; }
public Nullable<System.DateTime> Date { get; set; }
public Nullable<int> EmployeeID { get; set; }
public Nullable<int> SupplierID { get; set; }
public int ProductTypeID { get; set; }
public Nullable<decimal> CostPrice { get; set; }
public Nullable<int> Quantity { get; set; }
public virtual Employee Employee { get; set; }
public virtual ProductType ProductType { get; set; }
public virtual Supplier Supplier { get; set; }
}
}
below is a picture of Data set and error message
Crystal Reports' SetDataSource() method creates DataColumn supplied by list of ProductOrder, and then trying to build DataColumn instances that has nullable type, which is not supported.
You should either create a viewmodel class which has properties with same base types but without nullable types present, then project the result with that class as data source:
// Viewmodel
public class ProductOrderVM
{
public int OrderID { get; set; }
public DateTime Date { get; set; }
public int SupplierID { get; set; }
public decimal CostPrice { get; set; }
public int Quantity { get; set; }
}
// Controller action
rd.SetDataSource(db.ProductOrder.Select(p => new ProductOrderVM
{
OrderID = p.OrderID,
Date = p.Date.GetValueOrDefault(),
SupplierID = p.SupplierID.GetValueOrDefault(),
CostPrice = p.CostPrice.GetValueOrDefault(),
Quantity = p.Quantity.GetValueOrDefault()
}).ToList());
Or use null coalescing/ternary operator to assign default values according to their base type if the nullable properties have null value:
rd.SetDataSource(db.ProductOrder.Select(p => new
{
OrderID = p.OrderID,
// with ternary operator
Date = p.Date == null ? DateTime.MinValue : p.Date, // or DateTime.Now as default value
// with null-coalescing operator
SupplierID = p.SupplierID ?? 0,
CostPrice = p.CostPrice ?? 0,
Quantity = p.Quantity ?? 0
}).ToList());

Best way to parse a Gremlin.Net response?

What is the best way to get POCO's from a Gremlin.Net response?
Right now I manually cast to dictionaries:
var results = await gremlinClient.SubmitAsync<Dictionary<string, object>>("g.V()");
var result = results[0];
var properties = (Dictionary<string, object>)result["properties"];
var value = ((Dictionary<string, object>)properties["myValue"].Single())["value"];
I found that the GremlinClient can only return dynamic objects, if you put anything else as the type, it fails (unless I was just doing something wrong).
What I ended up doing was serialising the dynamic object to JSON and then deserialising it back to the object type I wanted:
var results = await gremlinClient.SubmitAsync<dynamic>("g.V()");
JsonConvert.DeserializeObject<MyResult>(JsonConvert.SerializeObject(results));
The dynamic object is just a Dictionary, but if you serialise it first it has the proper hierarchy of fields/properties which can then be deserialised to what you actually expect.
Seems a bit of a pain to have to do the extra conversion, but only way I got it to work.
You can get your properties by using MyClass similar to
class ProviderProperties {
public object Name { get; set; }
public object contact { get; set; }
public object requesttype { get; set; }
public object address { get; set; }
public object phone { get; set; }
public object description { get; set; }
public object otherState { get; set; }
public object otherCity { get; set; }
public object addressStreet { get; set; }
}
class MyClass {
public string id { get; set; }
public string label { get; set; }
public string type { get; set; }
public ProviderProperties properties { get; set; }
}
and using it in
JsonConvert.DeserializeObject<MyClass>(JsonConvert.SerializeObject(results));
Try this approach
IGremlinClient janusClient = JanusGraphClientBuilder.BuildClientForServer(new GremlinServer("localhost", 8182)).Create();
GraphTraversalSource g = Traversal().WithRemote(new DriverRemoteConnection(janusClient));
IList<Vertex> x = g.V().HasLabel("YourLabel").Has("YourpPopertyName", "some value").ToList();

using DataContractJsonSerializer when Json object propety is named with "#" symbol

When using DataContractJsonSerializer to parse a json response, I've come across a json object with a property name of #id and I can't seem to populate this field. All of the other fields are populated without a problem. I can even get this field populated using Fiddler, but not using DataContractJsonSerializer. My code is as follows...
public IEnumerable<Vehicle> vehicles { get; set; }
public async Task GetVehicleList(string access_token)
{
vehicles = await GetVehicleListInfo(access_token);
}
private async Task<IEnumerable<Vehicle>> GetVehicleListInfo(string access_token)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("https://www.example.com/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/vnd.example.api-v1+json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer" + access_token);
HttpResponseMessage response = await client.GetAsync("vehicles");
//IEnumerable<Vehicle> vehicles = new IEnumerable<Vehicle>();
Vehicle vehicle = new Vehicle();
PagedVehicleResult pvr = new PagedVehicleResult();
Stream dataStream = null;
if (response.IsSuccessStatusCode)
{
dataStream = await response.Content.ReadAsStreamAsync();
DataContractJsonSerializer serializer = new DataContractJsonSerializer(pvr.GetType());
pvr = (PagedVehicleResult)serializer.ReadObject(dataStream);
}
vehicles = pvr.vehicle;
return vehicles;
}
}
}
/// <summary>
/// parent object returned by json. contains list of vehicle objects
/// </summary>
public class PagedVehicleResult
{
public int count { get; set; }
public int index { get; set; }
public int limit { get; set; }
public int total { get; set; }
public string type { get; set; }
public IEnumerable<Vehicle> vehicle { get; set; }
}
public class Vehicle
{
public int id { get; set; } //This is the property in question.
//When it comes back in fiddler it looks like "#id", and it does get populated.
//when it comes back in my console application it is 0 if int and null if string.
public string vin { get; set; }
public string label { get; set; }
public string color { get; set; }
public string make { get; set; }
public string model { get; set; }
public string deviceSerialNumber { get; set; }
public int year { get; set; } //consider making date? unknown repercussions
public CreateTimestamp createdTimestamp { get; set; }
public ModifiedTimestamp modifiedTimestamp { get; set; }
}
public class CreateTimestamp
{
public string readOnly { get; set; }
public string value { get; set; } //had to cast as string.. can convert to datetime before database insert
}
public class ModifiedTimestamp
{
public string readOnly { get; set; }
public string value { get; set; }
}
How can I map that json #id field to my Vehicle class id property?
Okay, I figured this out on my own from reading various different post on the subject.
All I had to do was parse it into a json string first, then call a .replace() on the string to change the id. Then I used the JavaScriptSerializer on that and it worked.
if (response.IsSuccessStatusCode)
{
dataStream = await response.Content.ReadAsStreamAsync();
string content;
using (StreamReader reader = new StreamReader(dataStream, true))
{
content = reader.ReadToEnd();
content = content.Replace("#id", "id");
JavaScriptSerializer js = new JavaScriptSerializer();
pvr = js.Deserialize<PagedVehicleResult>(content);
}
}
vehicles = pvr.vehicle;
return vehicles;
Now, when i try, my object id is correctly inserted.

Asp Mvc model binding of array with content type application/x-www-form-urlencoded

Below is a POST url with content type application/x-www-form-urlencoded
POST
http://partner-site.com/api_implementation/hotel_availability
BODY
api_version=4
&hotels=[{"ta_id":97497,"partner_id":"229547","partner_url":"http://partner.com/deeplink/to/229547"},{"ta_id":97832,"partner_id":"id34234","partner_url":"http://partner.com/deeplink/to/id34234"}]
&start_date=2013-07-01
&end_date=2013-07-03
&num_adults=2
&num_rooms=1
&lang=en_US
&currency=USD
&user_country=US
&device_type=d
&query_key=6167a22d1f87d2028bf60a8e5e27afa7_191_1360299600000_2_2
CONTENT TYPE
application/x-www-form-urlencoded
And i have wrote the class that read like
public class HotelAvailabilityRequest
{
public int api_version { get; set; }
public List<HotelSummary> hotels { get; set; }
public string start_date { get; set; }
public string end_date { get; set; }
public int num_adults { get; set; }
public int num_rooms { get; set; }
public string lang { get; set; }
public string query_key { get; set; }
public string currency { get; set; }
public string user_country { get; set; }
public string device_type { get; set; }
}
public class HotelSummary
{
public int ta_id { get; set; }
public string partner_id { get; set; }
public string partner_url { get; set; }
}
When i use the HotelAvailabilityRequest in my ASP MVC method
public ActionResult Hotel_Availability(HotelAvailabilityRequest request)
{}
I'm getting other parameter like request.api_version, request.device_type except request.hotels
I'm getting request.hotels.Count() equal to zero.
How do i get the request.hotel to bind accordingly?
After a few round of testing, I resort to manually parsing and deserializing my query string. Since primitive types (int, string like request.api_version) are well captured by the default model binder, my focus is to resolve the complex object type (request.hotels) that is problem.
First, I get the full query string with
Request.InputStream.Position = 0;
var queryString = new StreamReader(Request.InputStream).ReadToEnd();
var queryStringCollection = HttpUtility.ParseQueryString(queryString);
Then, I deserialize the query string into the intended object list
var hotelStr = queryStringCollection.Get("hotels");
var requestHotels = (List<HotelSummary>) JsonConvert.DeserializeObject(hotelStr, typeof (List<HotelSummary>));
request.hotels = requestHotels;
Not the best solution but it works. Hope someone workout a better ModelBinder for ASP MVC that resolve complex object type at binding.

Resources