Uploading to documentDB is missing inner JSON members of complex objects - json

I am uploading data to the documentDB using the following code:
private static async Task UploadEntry(OptimizationData entry)
{
try
{
string endpointUrl = ConfigurationManager.AppSettings.Get("DocumentDBEndpointURL");
string authorizationKey = ConfigurationManager.AppSettings.Get("DocumentDBAuthKey");
string databaseId = ConfigurationManager.AppSettings.Get("DocumentDBDatabaseId");
string collectionName = ConfigurationManager.AppSettings.Get("CollectionName");
using (DocumentClient client = new DocumentClient(new Uri(endpointUrl), authorizationKey))
{
DocumentCollection documentCollection = client.CreateDocumentCollectionQuery("dbs/" + databaseId).Where(c => c.Id == collectionName).AsEnumerable().FirstOrDefault();
if (documentCollection != null)
{
await client.CreateDocumentAsync("dbs/" + databaseId + "/colls/" + documentCollection.Id, entry);
}
}
}
catch
{
//Ignored
}
}
Now my objects are of these types:
public class OptimizationData
{
[DataMember]
public string Id { get; set; }
[DataMember]
public Dictionary<DateTime,OptimizationEntry> Optimization;
}
And Optimization Entry looks like this:
[DataContract]
public class OptimizationEntry
{
[DataMember]
public decimal price{ get; set; }
public decimal optimalPrice { get; set; }
public decimal weight { get; set; }
}
The problem is, when I look into my document explorer on azure's portal, the inner items of the dictionary are missing. I.e., it has datetime, and the first item (price) but not optimialPrice and Weight
"Optimization": {
"2016-01-27T21:00:00": {
"price": 179.482711791992
},
"2016-01-27T22:00:00": {
"price": 196.533660888672
},
....
Is there a way I'm supposed to insert the document so that the inner objects are not missed?

To answer the question for possible future people who need help, the reason they were not showing was that the OptimizationEntry only had "price" as [DataMember] so that it could be serialized, the other two did not. Therefore JSON serialization did not include them in the upload.

Related

Deserializing a Json array of objects in xamarin forms not working

I have a json api response of something like this:
[
{
"id": 1,
"accountnumber": "001303000023",
"accounttitle": "MEGA CROWN ",
"accountdesc": "MEGA CROWN ",
"productType": "Loan",
"prodname": "SME TERM LOAN ",
"bookbalance": -200000.00,
"effectivebalance": -200000.000000,
"currentbalance": -200000.0000
},
{
"id": 2,
"accountnumber": "1020145429",
"accounttitle": "MEGA CROWN",
"accountdesc": "CORPORATE ",
"productType": "Current",
"prodname": "CORPORATE CURRENT ACCOUNT ",
"bookbalance": 3000.00,
"effectivebalance": 23000.000000,
"currentbalance": 3000.0000
}
]
and here is my model class...
public class Balance
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("productType")]
public string AccountType { get; set; }
[JsonProperty("accountnumber")]
public string AccountNumber { get; set; }
public string accounttitle { get; set; }
public string accountdesc { get; set; }
public string prodname { get; set; }
public double effectivebalance { get; set; }
public double currentbalance { get; set; }
[JsonProperty("currentbalance")]
public double balance { get; set; }
public string AccountBalance { get; set; }
//public string AccountBalance
//{
// get
// {
// string bal = this.balance.ToString();
// var newBal = Math.Round(Convert.ToDouble(bal), 2).ToString("C", System.Globalization.CultureInfo.GetCultureInfo("en-us")).Replace("$", "N");
// return newBal;
// }
// set
// {
// AccountBalance = value;
// }
//}
public ImageSource WalletImage
{
get
{
var img = ImageAsset.WalletImage;
return img;
}
set
{
WalletImage = value;
}
}
public Transaction transactions { get; set; }
}
I have tried different approaches to deserialize but all is futile.
first method I tried is this:
List<Balance> userAccts = JsonConvert.DeserializeObject<List<Balance>>(jsonee);
But nothing seem to work. whenever I put a breakpoint on the above deserializer method, the call gets to the point of deserialization but doesn't go beyond that. It's always returning to the previous call then overtime will break the house.
Please any help will be deeply appreciated.
Note: I have even tried to add "{}" into the response using stringFormatter so as to be able to deserialize into a list but all proof futile.
I also tried to serialize the response then deserialize it again.
Wrap deserialise method into try catch and check what error you get exactly.
You have added "currentbalance" twice. One as property and other one as JsonPropertyAttribute with same name. Please keep only one.
public double currentbalance { get; set; }
[JsonProperty("currentbalance")]
public double balance { get; set; }
A member with the name 'currentbalance' already exists on
'StackQA_Console1.Balance'. Use the JsonPropertyAttribute to specify
another name.
Same code works for me after keeping single "currentbalance" property.

Fetch JSON array using WebClient and Json.Net and display it in textview?

My Activity code is:
private void MClient_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
{
string json = Encoding.UTF8.GetString(e.Result);
var Details = JsonConvert.DeserializeObject(json);
}
My doctor.cs class code is:
namespace App12
{
public class Doctor
{
public string DoctorId { get; set; }
public string doctorName { get; set; }
public string specialityId { get; set; }
public string experiance { get; set; }
public string fee { get; set; }
}
public class RootObject
{
public Doctor doctor { get; set; }
}
}
JSON array is:
{
"0": {
"DoctorId": "1",
"doctorName": "DR.Rama",
"specialityId": "1",
"experiance": "5 years",
"fee": "300rs"
}
}
I am trying to show this in textview but it gives me an error:
System.InvalidCastException: Specified cast is not valid.
You have two problems here.
Your class structure doesn't quite match up with the shape of the JSON data. This JSON isn't technically an array either; it's a dictionary. You need to deserialize into a Dictionary<string, Doctor>.
When calling JsonConvert.DeserializeObject you need to specify a type parameter. If you don't, the return type will be JObject. This may be the cause of the InvalidCastException.
Try it like this:
var dict = JsonConvert.DeserializeObject<Dictionary<string, Doctor>>(json);
From there you can loop through the doctors like this:
foreach (var doctor in dict.Values)
{
textView.Append(doctor.doctorName);
}

Service Stack POST-Request Body-Format / Transformation

iam using a RequestClass with the Route anotation to call a Json-Client POST method.
Now, while the paramters are structured like this
public class GetTicketRequest: IReturn<JsonObject>
{
public string CartId {
get;
set;
}
public string PriceId {
get;
set;
}
}
The BackendAPI needs them to be nesten in "data" in the json request, so more like
{
"data":[
{"cartid":123,
"priceId":11}]
}
Is there any way to transfrom the request object for the body before calling
JsonServiceClient _restClient = new JsonServiceClient(baseUrl);
JsonObject oneResponse = _restClient.Post(options);
This solution is useful where many DTOs require to be wrapped & converted, and is highly reusable, with no changes to your existing DTOs.
You can convert the requests of the JsonServiceClient by overriding the methods that handle preparing the requests for sending. Which means implementing your own extended JsonServiceClient as given below.
If you want to do this for all verbs then you override it's Send<TResponse> methods (otherwise, if it's just for POST then uncomment the commented out code, and remove the Send methods).
public class MyJsonServiceClient : JsonServiceClient
{
public Dictionary<Type, Func<object, object>> DtoConverters = new Dictionary<Type, Func<object, object>>();
public MyJsonServiceClient() {}
public MyJsonServiceClient(string baseUri) : base(baseUri) {}
public MyJsonServiceClient(string syncReplyBaseUri, string asyncOneWayBaseUri) : base(syncReplyBaseUri, asyncOneWayBaseUri) {}
public override TResponse Send<TResponse>(object request)
{
return base.Send<TResponse>(ConvertRequest(request));
}
public override TResponse Send<TResponse>(string httpMethod, string relativeOrAbsoluteUrl, object request)
{
return base.Send<TResponse>(httpMethod, relativeOrAbsoluteUrl, ConvertRequest(request));
}
/*
public override TResponse Post<TResponse>(string relativeOrAbsoluteUrl, object requestDto)
{
return base.Post(relativeOrAbsoluteUrl, ConvertRequest(requestDto));
}
*/
object ConvertRequest(object request)
{
Type dtoType = request.GetType();
return (DtoConverters.ContainsKey(dtoType)) ? DtoConverters[dtoType](request) : request;
}
}
Usage:
So given this DTO:
[Route("/test", "POST")]
public class TicketRequest : IReturnVoid
{
public string CartId { get; set; }
public string PriceId { get; set; }
}
You simply add the converter:
var client = new MyJsonServiceClient("http://localhost:9000");
// Simple converter for TicketRequest
client.DtoConverters.Add(typeof(TicketRequest), dto => {
var d = (TicketRequest)dto;
return new {
data = new {
CartId = d.CartId.ToInt(),
PriceId = d.PriceId.ToInt()
}
};
});
client.Post(new TicketRequest { CartId = "123", PriceId = "456" });
i solved this issue using a typed data property
public class GetTicketRequest: IReturn<JsonObject>
{
public class TicketCreateData
{
public int priceId {
get;
set;
}
}
public string CartId {
get;
set;
}
public string PriceId {
get;
set;
}
public List<TicketCreateData> data {
get {
var list = new List<TicketCreateData>();
list.Add(new TicketCreateData {
priceId = this.PriceId.ToInt()
});
return list;
}
set {
data = value;
}
}
}
To notes on this:
if neede, use DataContract/DataMember(Name="") to rename fields or only do partial serializing
Do never use structs for, like in this case, the data class - they are not serializeable at all
in my spefici case data even needs to be an array, thats why i used the list

Azure Mobile Services (Windows Phone) - store complex object

I am playing around with Azure Mobile Services. Right now I am trying to store an object of my custom class in a table.
Here is a snippet from the class which represent the object which I want to store in Azure.
public class CustomItem : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public string Id { get; set; }
[JsonProperty(PropertyName = "Categorie")]
public CategorieObject Categorie { get; set; }
[JsonProperty(PropertyName = "Subcategorie")]
public SubcategorieObject Subcategorie { get; set; }
[JsonProperty(PropertyName = "Name")]
public string Name { get; set; }
...
}
My question is how to store custom types like CategorieObject or SubCategorieObject. These classes contain a String for the name and many other properties, but I only need to store the name of the Categorie and SubcategorieObject.
Maybe you can give me a hint, to solve my problem.
Thanks!
The post at http://blogs.msdn.com/b/carlosfigueira/archive/2012/09/06/supporting-arbitrary-types-in-azure-mobile-services-managed-client-complex-types.aspx shows one way to support complex objects in azure mobile service. For your scenario, you can send the data to the server and in the insert/read/update scripts you "change" the data to only store what you need. For example, assuming that you have those types on the client:
public class CustomItem : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public string Id { get; set; }
[JsonProperty(PropertyName = "Categorie")]
public CategorieObject Categorie { get; set; }
[JsonProperty(PropertyName = "Subcategorie")]
public SubcategorieObject Subcategorie { get; set; }
[JsonProperty(PropertyName = "Name")]
public string Name { get; set; }
}
public class CategorieObject
{
[JsonProperty(PropertyName = "Name")]
public string Name { get; set; }
[JsonProperty(PropertyName = "SomethingElse")]
public string SomethingElse { get; set; }
}
public class SubcategorieObject
{
[JsonProperty(PropertyName = "Name")]
public string Name { get; set; }
[JsonProperty(PropertyName = "SomethingElse")]
public string SomethingElse { get; set; }
}
You'd change your insert script to replace the complex object (categorie / subcategorie) with the name, which is what you want to store:
function insert(item, user, request) {
// Replace the complex object with their "Name" property.
// Omitting error / format checking here for conciseness.
item.Categorie = item.Categorie.Name;
item.Subcategorie = item.Subcategorie.Name;
request.execute({
success: function() {
// Recreate the original object
item.Categorie = { Name: item.Categorie };
item.Subcategorie = { Name: item.Subcategorie };
request.respond();
}
});
}
Likewise when updating an item you'd need to do the same:
function update(item, user, request) {
// Replace the complex object with their "Name" property.
// Omitting error / format checking here for conciseness.
item.Categorie = item.Categorie.Name;
item.Subcategorie = item.Subcategorie.Name;
request.execute({
success: function() {
// Recreate the original object
item.Categorie = { Name: item.Categorie };
item.Subcategorie = { Name: item.Subcategorie };
request.respond();
}
});
}
And the same for reading:
function read(query, user, request) {
request.execute({
success: function(results) {
results.forEach(function(item) {
item.Categorie = { Name: item.Categorie };
item.Subcategorie = { Name: item.Subcategorie };
});
request.respond();
}
});
}
Notice that any other properties in the subclasses will be lost when reading from the database (after all, you're not storing them).

Costomising the serialisation/serialised JSON in service stack

I need to turn this beutifull default JSON from Service Stack :
{
"Status": "ok",
"LanguageArray": [{
"Id": 1,
"Name": "English"
}, {
"Id": 2,
"Name": "Chinese"
}, {
"Id": 3,
"Name": "Portuguese"
}]
}
To this monstrosity of abomination:
{"status":"ok","language":{
"0":{"id":"1", "name":"English"},
"1":{"id":"2", "name":"Chinese"},
"2":{"id":"3", "name":"Portuguese"},
}
For reasons beyond my control or ration or logic.
My question is what are the simplest way of achieving this?
I need to do this to almost all Arrays ( they are IEnumerables implemented using List in C#)
I don't think I have a 'simplest way' and it kind of depends on where you need the serialization to happen as well as how strict the format is (case sensitive?, spacing?)
If place your example text and turn it into classes like this
public class Language
{
public int Id { get; set; }
public string Name { get; set; }
}
public class OuterLanguage
{
public string Status { get; set; }
public IEnumerable<Language> LanguageArray { get; set; }
}
A pretty straightforward way would be having a Dto that adds a property for serialization of the Array and ignores the original Array.
public class OuterLanguageDto
{
public string Status { get; set; }
[IgnoreDataMember]
public IEnumerable<Language> LanguageArray { get; set; }
public IDictionary<string, Language> language
{
get { return this.LanguageArray.ToDictionary(x => (x.Id - 1).ToString()); }
}
}
When you need to serialize your class (OuterLanguage) you use TranslateTo (or your preferred Mapper) and copy the values over to the Dto.
var jsonObj = obj.TranslateTo<OuterLanguageDto>();
var jsonStr = new JsonSerializer<OuterLanguageDto>().SerializeToString(jsonObj);
You could also look into Custom Serialization. That would give you to have a way to serialize all your Arrays into the correct format.
JsConfig<IEnumerable<Language>>.SerializeFn = ToJson
private string ToJson(IEnumerable<Language> arr)
{
var dict = arr.ToDictionary(x => x.Id - 1);
var str = JsonSerializer.SerializeToString<Dictionary<int, Language>>(dict);
return str;
}
However, I'm guessing you may have to do some "magic string work" to take your custom serialized Array's json string and format it properly when outer class (OuterLanguage in this example) is the one being serialized.