orleans: Bug in Json.Net: System.Int32 is deserialized as System.Int64
My state object produces errors during serialization in the Boolean object. Do I need to update to 1.1.1?
This is the object:
[JsonObject(MemberSerialization.OptIn)]
public class SiteState : global::Orleans.GrainState
{
[JsonProperty]
public AsSite Model { get; set; }
//defaults
[JsonProperty]
public int Threshold { get; set; }
[JsonProperty]
public bool DisableAlarms { get; set; }
}
and this is the error:
Data #1 Key=Model Value=Mesh.Ratatouille.Model.Site.AsSite Type=Mesh.Ratatouille.Model.Site.AsSite Data #2 Key=Threshold Value=0 Type=System.Int64 Data #3 Key=DisableAlarms Value=False Type=System.Boolean at Orleans.Storage.AzureTableStorage.ConvertFromStorageFormat(GrainState grainState, GrainStateEntity entity) at Orleans.Storage.AzureTableStorage.<ReadStateAsync>d__0.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at Orleans.Runtime.Scheduler.SchedulerExtensions.<>c__DisplayClassa.<<QueueTask>b__8>d__c.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at Orleans.Runtime.Catalog.<SetupActivationState>d__35.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at Orleans.Runtime.Catalog.<InitActivation>d__2b.MoveNext() Exc level 1: System.ArgumentException: Object of type ‘System.Int64’ cannot be converted to type ‘System.Int32’. at System.RuntimeType.TryChangeType(Object value, Binder binder, CultureInfo culture, Boolean needsSpecialCast) at System.RuntimeType.CheckValue(Object value, Binder binder, CultureInfo culture, BindingFlags invokeAttr) at System.Reflection.MethodBase.CheckArguments(Object[] parameters, Binder binder, BindingFlags invokeAttr, CultureInfo culture, Signature sig) at System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) at System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, Object[] index) at Orleans.GrainState.SetAll(IDictionary`2 values) at Orleans.Storage.AzureTableStorage.ConvertFromStorageFormat(GrainState grainState, GrainStateEntity entity)
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Comments: 17 (9 by maintainers)
@gabikliot
There are additional gotcha in this area that I discovered when deserializing using Json.NET with weak typing (i.e. when Json.NET doesn’t have specific type information during deserialization):
UInt64
with a value larger thanInt64.MaxValue
, it will deserialize into aBigInteger
instead of aUInt64
.Guid
will be deserialized asString
.System.Single
is deserialized intoSystem.Double
unless specified otherwise by JsonSerializerSettings.FloatParseHandling.Int64
, unlessStringEnumConverter
was used for serialization, then it will be deserialized as aString
. In any case, conversion should be tolerant to both.Due to all this, I’ve written my own conversion code to fix any loss of type information when converting to JSON, included below. It’s not perfect, and it evolves as I discover new corner cases, but it addresses some of the oddities you might encounter.