WP7 Json serializer doesn't handle "space"? - c#

I recently made a post here (which is now marked as "answered" - which it is) about parsing Google Calc json strings into WP7 http://www.google.com/ig/calculator?hl=en&q=100GBP=?SEK.
It's working great - unless Google returns a number above 999. A number above 999 is writenn 1 000, instead of 1000. It seems like the "space" makes the application crash/try-catch aware that there's something wrong.
I just wonder how I can make the json serializer (using System.Runtime.Serialization.Json;) (using StringBuilder) return sum/amount(s) above 999, without crashing?
Thanks :)
CODE:
Hello! I'm mainly using the code found here: Parse Google Calculator with Json in Windows Phone 7 / C#?
In order to get currency landcodes from listbox, I use:
ListBoxItem toExchangeSelected= toCurrencyList.ItemContainerGenerator.ContainerFromItem(this.toCurrencyListtaListe.SelectedItem) as ListBoxItem;
string toCurrency = toCurrencyList.Content.ToString();
ListBoxItem fromExchangeSelected= fromCurrencyList.ItemContainerGenerator.ContainerFromItem(this.fromCurrencyList.SelectedItem) as ListBoxItem;
string fromCurrency = fromExchangeSelected.Content.ToString();

Certain European cultures use spaces instead of commas for large numbers, so try using the appropriate CultureInfo before you parse the string:
CultureInfo ci = new CultureInfo("fr-FR");
double d = double.Parse("1 000", ci); // returns 1000.0

Try using the newtonsoft json serializer.
http://json.codeplex.com/
They have a binaries for wp7, and is better that the datacontractserializer (in my view)
I've just noticed that the second answer of your mentionned question on StackOverflow is the same as the one i'm talking about.
Use JsonConvert.Deserialize<T>(string json) with T as your result (ExchangeRate ?)

Related

Maintaining source string format when reading a date-time from a JSON path and writing it to another file

How can I have Newtonsoft.Json read the value of a path without converting or otherwise meddling with values?
This code
jsonObject.SelectToken("path.to.nested.value").ToString()
Returns this string
03/07/2019 00:02:12
From this string in the JSON document
2019-07-03T00:02:12.1542739Z
It's lost its original formatting, ISO 8601 in this case.
I would like all values to come through as strings, verbatim. I'm writing code to reshape JSON into other formats and I don't want to effect the values as they pass through my .NET code.
What do I need to change? I am not wedded to Newtonsoft.Json btw.
I got it, I think.
jsonObject.SelectToken(path).ToString(Newtonsoft.Json.Formatting.None);
The other options were to supply nothing or this.
Newtonsoft.Json.Formatting.Indented
Which is strange logic in this API as you'd think None means not indented but it means not ... I don't know. Hang on....
Okay so None or Indented returns
"2019-07-03T00:02:12.1542739Z"
(including quotes) but using the overload taking no parameters returns
03/07/2019 00:02:12
That's an odd API design ¯\_(ツ)_/¯
Here's a screenshot which shows really simple repro code.

How to use string format to omit period but leave digits

I have the format string ######.00 used for formatting decimals in C#. I need to change it so that it omits the period but keeps the digits following the period. Can I accomplish this just by changing the format? I've searched, but haven't been able to find a solution online.
I found this answer to a very similar question, but it involves multiplying the decimal by 100 before formatting it. I'm not able to manipulate the number going in, nor the resulting string because I don't have access to them. This is because we're using a function from a third-party library that fetches the number from elsewhere and displays it formatted to the UI. I can only provide it with a format string. (If manipulating the number or resulting string is the only way to get it in the format we can probably do it, it would just take a good deal of refactoring, so I wanted to see if there's a simpler solution first. Hence the constraints.)
Just as an example of the output I'm looking for, consider the following code:
var myFormat = "{0:######.00}";
Console.WriteLine(string.Format(myFormat, 1234.1234));
Console.WriteLine(string.Format(myFormat, 5));
The code above currently outputs 1234.12 and 5.00, but I would like it to output 123412 and 500 just by changing myFormat. Is there a way to do this?
If only the format string is what you can change, there's probably no way to remove the dot.
However, you can implement your own Formatter, as MSDN's example.
string.Format(new CustomerFormatter(), "{0}", 1234.1234)

String to Double Conversion (Comma to dot issue)

Struggling with the basics - I'm trying to code a simple currency converter. The XML provided by external source uses comma as a decimal separator for exchange rate (kurs_sredni):
<pozycja>
<nazwa_waluty>bat (Tajlandia)</nazwa_waluty>
<przelicznik>1</przelicznik>
<kod_waluty>THB</kod_waluty>
<kurs_sredni>0,1099</kurs_sredni>
</pozycja>
I already managed to load the data from XML into a nifty list of objects (kursyAktualne), and now i'm trying to do the math. I'm stuck with conversion.
First of all i'm assigning "kurs_sredni" to a string, trying to replace "," with "." and converting the hell out of it:
string kursS = kursyAktualne[iNa].kurs_sredni;
kursS.Replace(",",".");
kurs = Convert.ToDouble(kursS);
MessageBox.Show(kurs.ToString());
The messagebox show 1099 instead of expected 0.1099 and kursS still has comma, not dot.
Tried toying with some cultureInfo stuff i googled, but that was too random. I need to understand how to control this.
Just use decimal.Parse but specify a CultureInfo. There's nothing "random" about it - pick an appropriate CultureInfo, and then use that. For example:
using System;
using System.Globalization;
class Test
{
static void Main()
{
var french = CultureInfo.GetCultureInfo("fr-FR");
decimal value = decimal.Parse("0,1099", french);
Console.WriteLine(value.ToString(CultureInfo.InvariantCulture)); // 0.1099
}
}
This is just using French as one example of a culture which uses , as a decimal separator. It would probably make sense to use the culture of the origin of the data.
Note that decimal is a better pick for currency values than double - you're trying to represent an "artificial" construct which is naturally specified in base10, rather than a "natural" continuous value such as a weight.
(I would also be wary of a data provider who provides data in a non-standard format. If they're getting that wrong, who knows what else they'll get wrong. It's not like XML doesn't have a well-specified format for numbers...)
It is because Replace method returns new string with replaced characters. It does not modify your original string.
So you need to reassign it:
kursS = kursS.Replace(",",".");
Replace returns a string. So you need an assignment.
kursS = kursS.Replace(",", ".");
There is "neater" way of doing this by using CulturInfo. Look this up on the MSDN website.
You replace result isn't used, but the original value that doesn't contain the replace.
You should do:
kursS = kursS.Replace(",", ".")
In addition this method isn't really safe if there are thousands-separators.
So if you are not using culture settings you should do:
kursS = kursS.Replace(".", "").Replace(",", ".")

Fixing JSON Date serialization from .Net web method

I am currently working on a project where I am sending a .Net type via ajax to a client application via ajax. I have no issues with the object being serialized and set to the client.
I run into issues when I take the exactly same object and post it back to the server via a web method with the following error: /Date(1373950800000)/ is not a valid value for DateTime. Which is pretty annoying as that is how Microsoft gave it to me, but that's besides the point.
Does anyone have a quick fix for this? I want a seamless way this can be accomplished without having to change the object right before returning it from the ajax call.
Your issue comes down to the server-side JavaScript serializer you are using; either JsonDataContractSerializer (default serializer for ASP.NET MVC) or NewtonSoft Json Serializer (default serializer for ASP.NET Web API).
For a visual example of this date mangling issue as well as possible solutions, check out JSON Dates are Different in ASP.NET MVC and Web API.
Handle the DateFormat while serialization
following code will resolve your problem
JsonConvert.SerializeObject(yourobject, Formatting.Indented,
new JsonSerializerSettings
{
DateFormatHandling = DateFormatHandling.IsoDateFormat
});
It will result the dates in 2009-02-15T00:00:00Z format
This one will help you with the error: click me
var yourDateTimeObject = ...
var converter = new IsoDateTimeConverter();
string isoDateTime = Newtonsoft.Json.JsonConvert.SerializeObject(yourDateTimeObject, converter);
This is the method that I use for these things:
First you need to clean the junk out of the date parameter
String unixDate = "/Date(1373950800000)/";
unixDate = unixDate.Replace("/Date(","").Replace(")/", "");
Now, as .NET and unix measure time in a different way, you have to compensate for that by creating a date set to the 1st of Jan 1970 and then adding the numeric part of the date that you were passed
DateTime dotNetDate = new DateTime(1970, 1, 1);
dotNetDate = dotNetDate.AddMilliseconds(Convert.ToInt64(unixDate)
You should also note that there will a loss of precision here - .NET dates are to the nearest nanosecond where unix dates are to the nearest millisecond
Try sending the dates with the forward slashes escaped. I have an iPad client that posts JSON to an ASP.NET WebAPI service method and we have to send dates this way:
"due": "\/Date(1335830400000)\/"

Best way to parse float?

What is the best way to parse a float in CSharp?
I know about TryParse, but what I'm particularly wondering about is dots, commas etc.
I'm having problems with my website. On my dev server, the ',' is for decimals, the '.' for separator. On the prod server though, it is the other way round.
How can I best capture this?
I agree with leppie's reply; to put that in terms of code:
string s = "123,456.789";
float f = float.Parse(s, CultureInfo.InvariantCulture);
Depends where the input is coming from.
If your input comes from the user, you should use the CultureInfo the user/page is using (Thread.CurrentThread.CurrentUICulture).
You can get and indication of the culture of the user, by looking at the HttpRequest.UserLanguages property. (Not correct 100%, but I've found it a very good first guess) With that information, you can set the Thread.CurrentThread.CurrentUICulture at the start of the page.
If your input comes from an internal source, you can use the InvariantCulture to parse the string.
The Parse method is somewhat easier to use, if your input is from a controlled source. That is, you have already validated the string. Parse throws a (slow) exception if its fails.
If the input is uncontrolled, (from the user, or other Internet source) the TryParse looks better to me.
If you want persist values ( numbers, date, time, etc... ) for internal purpose. Everytime use "InvariantCulture" for formating & parsing values. "InvariantCulture" is same on every computer, every OS with any user's culture/language/etc...
string strFloat = (15.789f).ToString(System.Globalization.CultureInfo.InvariantInfo);
float numFloat = float.Parse(System.Globalization.CultureInfo.InvariantInfo, strFloat);
string strNow = DateTime.Now.ToString(System.Globalization.CultureInfo.InvariantInfo);
DateTime now = DateTime.Parse(System.Globalization.CultureInfo.InvariantInfo, strNow);
You could always use the overload of Parse which includes the culture to use?
For instance:
double number = Double.Parse("42,22", new CultureInfo("nl-NL").NumberFormat); // dutch number formatting
If you have control over all your data, you should use "CultureInfo.InvariantCulture" in all of your code.
Use a neutral culture (or one you know) when parsing with Try/Parse.
Pass in a CultureInfo or NumberFormatInfo that represents the culture you want to parse the float as; this controls what characters are used for decimals, group separators, etc.
For example to ensure that the '.' character was treated as the decimal indicator you could pass in CultureInfo.InvariantCulture (this one is typically very useful in server applications where you tend to want things to be the same irrespective of the environment's culture).
Try to avoid float.Parse, use TryParse instead as it performs a lot better but does the same job.
this also applies to double, DateTime, etc...
(some types also offer TryParseExact which also performs even better!)
The source is an input from a website. I can't rely on it being valid. So I went with TryParse as mentioned before.
But I can't figure out how to give the currentCulture to it.
Also, this would give me the culture of the server it's currently running on, but since it's the world wide web, the user can be from anywhere...
you can know current Cuklture of your server with a simple statement:
System.Globalization.CultureInfo culture = System.Globalization.CultureInfo.CurrentCulture;
Note that there id a CurrentUICulture property, but UICulture is used from ResourceMeanager form multilanguages applications. for number formatting, you must considere CurrentCulture.
I hope this will help you
One approach is to force localization to use dot instead of comma separator - this way your code will work identically on all windows machines independently from selected language and settings.
This approach is applicable to small gained applications, like test applications, console applications and so on. For application, which was localization in use this is not so useful, but depends on requirements of application.
var CurrentCultureInfo = new CultureInfo("en", false);
CurrentCultureInfo.NumberFormat.NumberDecimalSeparator = ".";
CurrentCultureInfo.NumberFormat.CurrencyDecimalSeparator = ".";
Thread.CurrentThread.CurrentUICulture = CurrentCultureInfo;
Thread.CurrentThread.CurrentCulture = CurrentCultureInfo;
CultureInfo.DefaultThreadCurrentCulture = CurrentCultureInfo;
This code forces to use dot ('.') instead of comma, needs to be placed at application startup.
Since you don't know the web user's culture, you can do some guesswork. TryParse with a culture that uses , for separators and . for decimal, AND TryParse with a culture that uses . for separators and , for decimal. If they both succeed but yield different answers then you'll have to ask the user which they intended. Otherwise you can proceed normally, given your two equal results or one usable result or no usable result.

Categories