Deserialize JSON into List with X++ - json.net

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;
}

Related

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();

ServiceStack OrmLite CustomSelect not working?

I'm trying to use the feature documented here :
https://github.com/ServiceStack/ServiceStack.OrmLite#custom-sql-customizations
This is how I'm using it:
var q = Db.From<MemberAccess>().LeftJoin<Member>();
return Db.Select<MemberResponse>(q);
Response object:
public class MemberResponse
{
public Guid Id { get; set; }
public string MemberFirstName { get; set; }
public string MemberLastName { get; set; }
public string MemberEmail { get; set; }
[Default(OrmLiteVariables.SystemUtc)]
public string AccessedOn { get; set; }
[CustomSelect("CONCAT(LEFT(Member.FirstName, 1),LEFT(Member.LastName,1))")]
public string MemberInitial { get; set; }
}
It seems like whatever I put in CustomSelect doesn't get used. Maybe, I'm not using this correctly? Also, the Default attribute doesn't work either.I tried that as it was an example from the doco.
Any idea will be appreciated.
Thanks in advance.
The [CustomSelect] only applies to the source table. Selecting the results in a custom type is used to map the returned resultset on the MemberResponse type, it doesn't have any effect on the query that gets executed.
Likewise with [Default(OrmLiteVariables.SystemUtc)] that's used to define the default value when creating the table which is only used when it creates the Column definition, so it's only useful on the source Table Type.
Both these attributes should only be added on the source MemberAccess to have any effect, which your mapped MemberResponse can access without any attributes, e.g:
public class MemberResponse
{
public Guid Id { get; set; }
public string MemberFirstName { get; set; }
public string MemberLastName { get; set; }
public string MemberEmail { get; set; }
public string AccessedOn { get; set; }
public string MemberInitial { get; set; }
}
Sql.Custom() API
The new Sql.Custom() API added in v4.5.5 that's available on MyGet will let you select a custom SQL Fragment, e.g:
var q = Db.From<MemberAccess>().LeftJoin<Member>()
.Select<MemberAccess,Member>((a,m) => new {
Id = a.Id,
MemberFirstName = m.FirstName,
MemberLastName = m.LastName,
MemberEmail = m.Email,
MemberInitial = Sql.Custom("CONCAT(LEFT(Member.FirstName,1),LEFT(Member.LastName,1))")
});
return Db.Select<MemberResponse>(q);

View Model with a List

If I construct a View Model with a List like this:
public class ProductsViewModel
{
public bool ProductBool { get; set; }
public string ProductString { get; set; }
public int ProductInteger { get; set; }
public List<Product> ProductList { get; set; }
}
it works fine. But I've seen code that constructs a similar Model like so:
public class ProductsViewModel
{
public bool ProductBool { get; set; }
public string ProductString { get; set; }
public int ProductInteger { get; set; }
public List<Product> ProductList { get; set; }
public ProductsViewModel()
{
this.ProductList = new List<Product>();
}
}
What does the extra contructor element actually do?
When you create an object of the class ProductsViewModel with the statement:
ProductsViewModel obj = new ProductsViewModel();
It automatically instantiate the ProductList. The values in obj now are:
ProductBool = false;ProductString = null;ProductInteger = 0;ProductList = new ProductList();
If you write obj.ProductList.Count() it will give 0
If you remove this constructor or the statement inside the constructor and create object of Class ProductsViewModel as created above. The values in obj will be:
ProductBool = false;ProductString = null;ProductInteger = 0;ProductList =null
If you write obj.ProductList.Count() it will give
Exception of NullReference

DocumentDB LAMBDA SqlMethod.Like and .Contains NotImplemented Exception

Im trying to do a simple "LIKE" query using a LAMBDA expression using CreateDocumentQuery; however after trying .Contains and SqlMethod.Like and both times receiving the response NotImplementedException I don't know what to try next!
Update: As of 5/6/15, DocumentDB added a set of String functions including STARTSWITH, ENDSWITH, and CONTAINS. Please note that most of these functions do not run on the index and will force a scan.
LIKE and CONTAINS are not yet supported in DocumentDB.
You'll want to check out the DocumentDB feedback page and vote on features (e.g. LIKE and CONTAINS) to get your voice heard!
Because I only needed to search against a discreet subset of properties of the larger object I implemented a .Contains search function as below. It works as expected though I have no idea regarding performance or scalability.
Domain Models
public interface ITaxonomySearchable
{
string Name { get; set; }
string Description { get; set; }
}
public class TaxonomySearchInfo : ITaxonomySearchable {
[JsonProperty(PropertyName = "id")]
public Guid Id { get; set; }
[JsonProperty(PropertyName = "name")]
public string Name { get; set; }
[JsonProperty(PropertyName = "description")]
public string Description { get; set; }
}
public class TaxonomyContainer : ITaxonomySearchable
{
[JsonProperty(PropertyName = "id")]
public Guid Id { get; set; }
[JsonProperty(PropertyName = "userId")]
public string UserId { get; set; }
[JsonProperty(PropertyName = "name")]
public string Name { get; set; }
[JsonProperty(PropertyName = "description")]
public string Description { get; set; }
[JsonProperty(PropertyName = "tags")]
public string[] Tags { get; set; }
[JsonProperty(PropertyName = "taxonomy")]
public Node[] Taxonomy { get; set; }
}
Search method
public async static Task<List<TaxonomySearchInfo>> Search(string searchTerm)
{
var db = GetJsonDocumentDb.GetDb();
using (var client = GetJsonDocumentDb.GetClient())
{
var documentCollection = await GetJsonDocumentDb.GetDocumentCollection(db, client, "TaxonomyContainerCollection");
return client.CreateDocumentQuery<TaxonomySearchInfo>(documentCollection.DocumentsLink)
.AsEnumerable()
.Where(r => r.Name.Contains(searchTerm) || r.Description.Contains(searchTerm))
.ToList();
}
}

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