Encoding NaN to JSON - json

My server uses ServiceStack to produce JSON, and I need to send double[] arrays containing NaNs to the browsers.
Since there's no standard way of encoding NaNs in JSON, it's not surprising that
ServiceStack produces invalid JSON in presence of NaNs
(e.g. [0,NaN,42]). I chose string values as my custom representation of NaNs (and ±Inf by the way):
[0,"NaN",42,"Inf","-Inf"] as an example. (Of course I implemented the necessary post-processing on the browser side, too).
I managed to do it by setting JsConfig<double>.RawSerializeFn to an encoder function.
That was fine, until I realized that as a side effect all DTO properties of type double
disappear from their JSON representation when the value is 0.
EDIT: this can be demonstrated by new KeyValuePair<double, double>(0, 1).ToJson()
which returns {"Key":0,"Value":1} when JsConfig<double>.RawSerializeFn is unset,
but returns {"Value":1} when JsConfig<double>.RawSerializeFn is set.
This change is a side effect that I want to avoid. (But my core problem is the transmitting of NaNs without sacrificing zero-valued DTO properties.)
I browsed the source code
of ServiceStack and it confirmed that the presence
of a custom RawSerializeFn activates the Equals(DefaultValue,propertyValue) check
(by causing propertySuppressDefaultConfig==true), which was omitted by default.
AFAICS the only way to avoid this check is setting JsConfig.IncludeNullValues=true,
which is bad because it cannot be done for double values only. I need the
default behavior: omitting properties with null values (for reference types) and include 0.0 double values in the generated JSON.
How to achieve these?

This custom RawSerializeFn emits 0 values in the latest version of ServiceStack.Text
JsConfig<double>.IncludeDefaultValue = true;
JsConfig<double>.RawSerializeFn = d =>
double.IsPositiveInfinity(d) ?
"\"+Inf\""
: double.IsNegativeInfinity(d) ?
"\"-Inf\""
: double.IsNaN(d) ?
"\"NaN\""
: d.ToString();
var doubles = new[] {
0.0, 1.0, double.NegativeInfinity, double.NaN, double.PositiveInfinity };
doubles.ToJson().Print(); // [0,1,"-Inf","NaN","+Inf"]
new KeyValuePair<double, double>(0, 1).ToJson().Print(); // {"Key":0,"Value":1}

Related

Codeeffects - Cannot load rule on UI that has In Rule Method with more than 255 string parameter value

It seems that CodeEffect library 4.3.2.6 has an issue with rule XML editing ON UI and transformation back from stroage to show it on UI for editing when rule XML has In Rule method call with string parameter that has string value passed in longer than 255 characters.
Is it made intentionally to avoid long rules to be edited on UI or just a bug so someone knows workaround for it?
To avoid any side effects from my code I downloaded and used Business Rule code example from codeeffects site Code Effects Demo Projects and opened it in VS2015.
In "Patient.cs" file added following code to
public class Patient
{
...
// In Rule Method that accepts only one string parameter
[Method("[NumberOfSegments]")]
public int RuleMethod01(
// explicitly specify maximum string allowed
[Parameter(ValueInputType.User,Max = 10000)]
string val)
{
return val.Split(',').Length;
}
}
On UI(using Ajax controller) I attempted to create rule with long string parameter passed in (in real project I need such long string since it contains unique parameters for In Rule method to use for calculations and cannot rely on the data sources approach that CodeEffects can offer)
Check if [NumberOfSegments] ("1111,2222,33333,4444,55555,6666,777,8888,999,0000,1111,222,333,44444,1231231,123123123,123123123,123123123,123123123,123123123,123123123,123123123,123123123,123132123,123123123,123123123,123123123,123123123,12123123,123123123,123123123,123123123,1231231233") greater than 12
But even that I explicitly specified maximum string length for parameter as 10000 in attribute Parameter UI does not allow me to enter string that has length more than 256 characters.
Documentation on CodeEffects site
Business-Rules-Data-Types does not mentioned any built-in restrictions and only way to restrict length of the string parameter use Parameter Attribute and its Max property.
Did anyone ran into the issue with such "synthetic" restrictions and can point me to the documentation or any workaround for that?
Thank you in advance for the any meaningful suggestions
PS: Just small update - when I manually edited Rule XML file and provided longer string as parameter (e.g. around 500 characters) I could not load it from the XML back to the UI the RuleEditor::Rule::InvalidElements collection contained one element with Hint property value "v122" dont know if its helpful but may be CodeEffects authors can know more about such Hint and what v122 means.
Strings longer than 255 chars (neither property values nor method params) are not supported in Code Effects. v122 is the error number that you get in response. Its original message is "The length of the value of this string element exceeds the maximum allowed limit".

Fluent bind not working as expected

Suppose I am binding using
bs.Bind(y)
.For(v => v.Visibility)
.To("Failures['TaxPercent'].Length")
.WithConversion("Visibility")
.WithFallback(false);
Where Failures is a dictionary which would contain the property name (e.g. TaxPercent) if, and only if, the property fails validation.
Therefore Failure['TaxPercent'] returns the validation failure message (e.g value missing).
I want to have an expandable textview in Android which is visible only when the error is detected. I used the above code and it is not working. The fallback value does not trigger when Failure['TaxPercent'] does not exist in the dictionary.
How do I get an expandable/collapsible textview based on the validation result using a dictionary in the viewmodel??? I would really like to use a dictionary because that would save me from creating IsErrorVisible for each property.
Oddly enough, using a dictionary works for retrieving the error message though, but not for visibility! In other words, this is working great
bs.Bind(y)
.For(v => v.Text)
.To("Failures['TaxPercent']");
Also, any reason why I cannot concatenate the binding, meaning can I do this???
bs.Bind(y)
.For(v => v.Text)
.To("Failures['TaxPercent']")
.For(v => v.Visibility)
.To("Failures['TaxPercent'].Length")
.WithConversion("Visibility")
.WithFallback(false);
EDIT
The error msg in the log is
MvxBind:Error:168.86 Problem seen during binding execution for binding Visibility for Failures['TaxPercent'].Length - problem ArgumentException: The value passed in must be an enum base or an underlying type for an enum, such as an Int32.
If the dictionary doesn't contain an entry for 'TaxPercent' then the expression Failures['TaxPercent'].Length will not evaluate (an exception will be throw) so UnsetValue will be used.
In the case of UnsetValue, the ValueConverter will not be called, and the Fallback will be used. This is the same pattern as in Wpf - http://msdn.microsoft.com/en-us/library/system.windows.dependencyproperty.unsetvalue(v=vs.110).aspx
For your particular situation, it looks like you could either:
change the Fallback to the correct value for the platform instead of to a boolean value (the question didn't specify which platform(s) you are using)
create a new Visibility ValueConverter that takes Failures as its binding source and 'TaxPercent' as its parameter
remove the .Length from your binding expression - just test on the existence of the entry.
you could switch to free text binding expressions - then you could do more complicated binding statements, including nested bindings, multiple value converters, multiple fallback values, ...
For this particular case, I would just drop the .Length
For "any reason why I cannot concatenate", that won't work as the return type of Bind is a single Fluent binding entry - not a Fluent binding set.

Dart objects with strong typing from JSON

I'm learning Dart and was reading the article Using Dart with JSON Web Services, which told me that I could get help with type checking when converting my objects to and from JSON. I used their code snippet but ended up with compiler warnings. I found another Stack Overflow question which discussed the same problem, and the answer was to use the #proxy annotation and implement noSuchMethod. Here's my attempt:
abstract class Language {
String language;
List targets;
Map website;
}
#proxy
class LanguageImpl extends JsonObject implements Language {
LanguageImpl();
factory LanguageImpl.fromJsonString(string) {
return new JsonObject.fromJsonString(string, new LanguageImpl());
}
noSuchMethod(i) => super.noSuchMethod(i);
}
I don't know if the noSuchMethod implementation is correct, and #proxy seems redundant now. Regardless, the code doesn't do what I want. If I run
var lang1 = new LanguageImpl.fromJsonString('{"language":"Dart"}');
print(JSON.encode(lang1));
print(lang1.language);
print(lang1.language + "!");
var lang2 = new LanguageImpl.fromJsonString('{"language":13.37000}');
print(JSON.encode(lang2));
print(lang2.language);
print(lang2.language + "!");
I get the output
{"language":"Dart"}
Dart
Dart!
{"language":13.37}
13.37
type 'String' is not a subtype of type 'num' of 'other'.
and then a stacktrace. Hence, although the readability is a little bit better (one of the goals of the article), the strong typing promised by the article doesn't work and the code might or might not crash, depending on the input.
What am I doing wrong?
The article mentions static types in one paragraph but JsonObject has nothing to do with static types.
What you get from JsonObject is that you don't need Map access syntax.
Instead of someMap['language'] = value; you can write someObj.language = value; and you get the fields in the autocomplete list, but Dart is not able to do any type checking neither when you assign a value to a field of the object (someObj.language = value;) nor when you use fromJsonString() (as mentioned because of noSuchMethod/#proxy).
I assume that you want an exception to be thrown on this line:
var lang2 = new LanguageImpl.fromJsonString('{"language":13.37000}');
because 13.37 is not a String. In order for JsonObject to do this it would need to use mirrors to determine the type of the field and manually do a type check. This is possible, but it would add to the dart2js output size.
So barring that, I think that throwing a type error when reading the field is reasonable, and you might have just found a bug-worthy issue here. Since noSuchMethod is being used to implement an abstract method, the runtime can actually do a type check on the arguments and return values. It appears from your example that it's not. Care to file a bug?
If this was addressed, then JsonObject could immediate read a field after setting it to cause a type check when decoding without mirrors, and it could do that check in an assert() so that it's only done in checked mode. I think that would be a nice solution.

Date Issue when migrating code from WCF to Web API

I'm working on a iOS application, that used to work using WCF.
We're changing this product to use MVC Web API instead of WCF.
I'm facing a problem with the dates! they must bebin JSON format such like
/Date(1373476260000-0600)/
But what is returned actually is of this format
/Date(1379484000000)/
which is not accepted by iOS controller and produces the default date value (like if it's null and it's just initializing it to the default value (12/31/1969))
I've tried to parse the date to the wanted JSON format date string, but it resulted in an exception because it's expecting a DateTime object instead.
I've also tried to add the following line:
GlobalConfiguration.Configuration.Formatters.JsonFormatter. SerializerSettings.DateParseHandling = Newtonsoft.Json.DateParseHandling.DateTimeOffset;
to the WebApiConfig.cs file but it's not working, then I've tried to add it to the AttributeRoutingHttpConfig.cs file then to the Global.asax but no response!
Then I've tried:
var appXmlType = GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
ValueProviderFactories.Factories.Add(new JsonValueProviderFactory());
also added them to the 3 files mentioned above but it didn't work!
Any ideas how to solve this?
P.S: I only have access to the Web API code! I can't alter the iOS code!
Thanks.
First, be sure you have set:
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings
.DateFormatHandling = Newtonsoft.Json.DateFormatHandling.MicrosoftDateFormat;
Otherwise you will get the ISO8601 format instead of the Microsoft format. (ISO8601 is much better, but you said you can't change the iOS app.)
Then, you need to realize that for DateTime values, the .Kind has an effect on how the serialization works. If you have one with DateTimeKind.Utc, then it will not contain an offset because that's how this particular format works.
If you want to ensure that an offset is always produced, then use the DateTimeOffset value instead. This will provide an offset of +0000 for UTC.
For example:
var settings = new JsonSerializerSettings
{
DateFormatHandling = DateFormatHandling.MicrosoftDateFormat
};
var dt = DateTimeOffset.UtcNow;
var json = JsonConvert.SerializeObject(dt, settings);
Debug.WriteLine(json); // "\/Date(1383153418477+0000)\/"
But you need to be very careful with this approach that all consumers honor the offset. For example, if a client receives this and parses it into a DateTime using WCF's DataContractJsonSerializer, there's a known bug that any offset will be treated as if it was the local time of the receiving computer, regardless of what the value of that offset actually is.
If at all possible, you should switch over both the server and the application to use ISO8601 formatting instead.
It seems the time zone portion of the date gets lost - try setting this in WebApiConfig:
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Local;

What is the best way to handle versioning using JSON protocol?

I am normally writing all parts of the code in C# and when writing protocols that are serialized I use FastSerializer that serializes/deserializes the classes fast and efficient. It is also very easy to use, and fairly straight-forward to do "versioning", ie to handle different versions of the serialization. The thing I normally use, looks like this:
public override void DeserializeOwnedData(SerializationReader reader, object context)
{
base.DeserializeOwnedData(reader, context);
byte serializeVersion = reader.ReadByte(); // used to keep what version we are using
this.CustomerNumber = reader.ReadString();
this.HomeAddress = reader.ReadString();
this.ZipCode = reader.ReadString();
this.HomeCity = reader.ReadString();
if (serializeVersion > 0)
this.HomeAddressObj = reader.ReadUInt32();
if (serializeVersion > 1)
this.County = reader.ReadString();
if (serializeVersion > 2)
this.Muni = reader.ReadString();
if (serializeVersion > 3)
this._AvailableCustomers = reader.ReadList<uint>();
}
and
public override void SerializeOwnedData(SerializationWriter writer, object context)
{
base.SerializeOwnedData(writer, context);
byte serializeVersion = 4;
writer.Write(serializeVersion);
writer.Write(CustomerNumber);
writer.Write(PopulationRegistryNumber);
writer.Write(HomeAddress);
writer.Write(ZipCode);
writer.Write(HomeCity);
if (CustomerCards == null)
CustomerCards = new List<uint>();
writer.Write(CustomerCards);
writer.Write(HomeAddressObj);
writer.Write(County);
// v 2
writer.Write(Muni);
// v 4
if (_AvailableCustomers == null)
_AvailableCustomers = new List<uint>();
writer.Write(_AvailableCustomers);
}
So its easy to add new things, or change the serialization completely if one chooses to.
However, I now want to use JSON for reasons not relevant right here =) I am currently using DataContractJsonSerializer and I am now looking for a way to have the same flexibility I have using the FastSerializer above.
So the question is; what is the best way to create a JSON protocol/serialization and to be able to detail the serialization as above, so that I do not break the serialization just because another machine hasn't yet updated their version?
The key to versioning JSON is to always add new properties, and never remove or rename existing properties. This is similar to how protocol buffers handle versioning.
For example, if you started with the following JSON:
{
"version": "1.0",
"foo": true
}
And you want to rename the "foo" property to "bar", don't just rename it. Instead, add a new property:
{
"version": "1.1",
"foo": true,
"bar": true
}
Since you are never removing properties, clients based on older versions will continue to work. The downside of this method is that the JSON can get bloated over time, and you have to continue maintaining old properties.
It is also important to clearly define your "edge" cases to your clients. Suppose you have an array property called "fooList". The "fooList" property could take on the following possible values: does not exist/undefined (the property is not physically present in the JSON object, or it exists and is set to "undefined"), null, empty list or a list with one or more values. It is important that clients understand how to behave, especially in the undefined/null/empty cases.
I would also recommend reading up on how semantic versioning works. If you introduce a semantic versioning scheme to your version numbers, then backwards compatible changes can be made on a minor version boundary, while breaking changes can be made on a major version boundary (both clients and servers would have to agree on the same major version). While this isn't a property of the JSON itself, this is useful for communicating the types of changes a client should expect when the version changes.
Google's java based gson library has an excellent versioning support for json. It could prove a very handy if you are thinking going java way.
There is nice and easy tutorial here.
It doesn't matter what serializing protocol you use, the techniques to version APIs are generally the same.
Generally you need:
a way for the consumer to communicate to the producer the API version it accepts (though this is not always possible)
a way for the producer to embed versioning information to the serialized data
a backward compatible strategy to handle unknown fields
In a web API, generally the API version that the consumer accepts is embedded in the Accept header (e.g. Accept: application/vnd.myapp-v1+json application/vnd.myapp-v2+json means the consumer can handle either version 1 and version 2 of your API) or less commonly in the URL (e.g. https://api.twitter.com/1/statuses/user_timeline.json). This is generally used for major versions (i.e. backward incompatible changes). If the server and the client does not have a matching Accept header, then the communication fails (or proceeds in best-effort basis or fallback to a default baseline protocol, depending on the nature of the application).
The producer then generates a serialized data in one of the requested version, then embed this version info into the serialized data (e.g. as a field named version). The consumer should use the version information embedded in the data to determine how to parse the serialized data. The version information in the data should also contain minor version (i.e. for backward compatible changes), generally consumers should be able to ignore the minor version information and still process the data correctly although understanding the minor version may allow the client to make additional assumptions about how the data should be processed.
A common strategy to handle unknown fields is like how HTML and CSS are parsed. When the consumer sees an unknown fields they should ignore it, and when the data is missing a field that the client is expecting, it should use a default value; depending on the nature of the communication, you may also want to specify some fields that are mandatory (i.e. missing fields is considered fatal error). Fields added within minor versions should always be optional field; minor version can add optional fields or change fields semantic as long as it's backward compatible, while major version can delete fields or add mandatory fields or change fields semantic in a backward incompatible manner.
In an extensible serialization format (like JSON or XML), the data should be self-descriptive, in other words, the field names should always be stored together with the data; you should not rely on the specific data being available on specific positions.
Don't use DataContractJsonSerializer, as the name says, the objects that are processed through this class will have to:
a) Be marked with [DataContract] and [DataMember] attributes.
b) Be strictly compliant with the defined "Contract" that is, nothing less and nothing more that it is defined. Any extra or missing [DataMember] will make the deserialization to throw an exception.
If you want to be flexible enough, then use the JavaScriptSerializer if you want to go for the cheap option... or use this library:
http://json.codeplex.com/
This will give you enough control over your JSON serialization.
Imagine you have an object in its early days.
public class Customer
{
public string Name;
public string LastName;
}
Once serialized it will look like this:
{ Name: "John", LastName: "Doe" }
If you change your object definition to add / remove fields. The deserialization will occur smoothly if you use, for example, JavaScriptSerializer.
public class Customer
{
public string Name;
public string LastName;
public int Age;
}
If yo try to de-serialize the last json to this new class, no error will be thrown. The thing is that your new fields will be set to their defaults. In this example: "Age" will be set to zero.
You can include, in your own conventions, a field present in all your objects, that contains the version number. In this case you can tell the difference between an empty field or a version inconsistence.
So lets say: You have your class Customer v1 serialized:
{ Version: 1, LastName: "Doe", Name: "John" }
You want to deserialize into a Customer v2 instance, you will have:
{ Version: 1, LastName: "Doe", Name: "John", Age: 0}
You can somehow, detect what fields in your object are somehow reliable and what's not. In this case you know that your v2 object instance is coming from a v1 object instance, so the field Age should not be trusted.
I have in mind that you should use also a custom attribute, e.g. "MinVersion", and mark each field with the minimum supported version number, so you get something like this:
public class Customer
{
[MinVersion(1)]
public int Version;
[MinVersion(1)]
public string Name;
[MinVersion(1)]
public string LastName;
[MinVersion(2)]
public int Age;
}
Then later you can access this meta-data and do whatever you might need with that.