尽管有JsonSerializer设置,SignalR仍未序列化NodaTime类型

时间:2016-06-01 22:34:16

标签: serialization json.net signalr nodatime

我正在使用NodaTime类型和SignalR参数(例如

)进行序列化问题(例外)
Error converting value to type 'NodaTime.ZonedDateTime

Error converting value \"2016-06-01T18:33:36.7279685+01 Europe/London\" to type 'NodaTime.ZonedDateTime'. Path '[0].DateCreated', line 1, position 79.

尽管遵循docs并且替换了默认的JsonSerializer并使用NodaTime扩展方法和JSON.net nuget包,例如

JsonSerializerSettings js = new JsonSerializerSettings();
js.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);
var serializer = JsonSerializer.Create(js);
GlobalHost.DependencyResolver.Register(typeof(JsonSerializer), () => serializer);

1 个答案:

答案 0 :(得分:2)

由于here

,很高兴找到BrannonKing的解决方法

本质上,它使用Customer Resolver for SignalR参数,它使用正确的序列化程序而不是创建默认值。

同样在SO here上引用,但当然只发现曾经开始发表我自己的问题;)

专门针对其他人(专访)NodaTime进行重新发布,并分享我需要的其他一些序列化修复,例如:

Newtonsoft.Json.JsonSerializationException: Self referencing loop detected for property X with type Y Path Z

服务器启动

public void Configuration(IAppBuilder app)
{
    JsonSerializerSettings js = new JsonSerializerSettings();
    js.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);
    js.DateParseHandling = DateParseHandling.None;
    js.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
    js.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
    var serializer = JsonSerializer.Create(js);
    GlobalHost.DependencyResolver.Register(typeof(JsonSerializer), () => serializer);
    var resolver = new Resolver(serializer);
    GlobalHost.DependencyResolver.Register(typeof(IParameterResolver), () => resolver);
}

自定义参数解析器

public class Resolver : DefaultParameterResolver
    {
        private readonly JsonSerializer _serializer;

        public Resolver(JsonSerializer serializer)
        {
            _serializer = serializer;
        }

        private FieldInfo _valueField;
        public override object ResolveParameter(ParameterDescriptor descriptor, Microsoft.AspNet.SignalR.Json.IJsonValue value)
        {
            if(value.GetType() == descriptor.ParameterType)
            {
                return value;
            }

            if(_valueField == null)
                _valueField = value.GetType().GetField("_value", BindingFlags.Instance | BindingFlags.NonPublic);

            var json = (string)_valueField.GetValue(value);
            using(var reader = new StringReader(json))
                return _serializer.Deserialize(reader, descriptor.ParameterType);
        }
    }

非常感谢Brannon!