2016-05-25 4 views
4

У меня возникает проблема десериализации значений времени в LocalTime-предоставлена, я довольно новичок в NodaTime. Я хочу импортировать результат веб-службы, в котором указано время в формате «HH: mm». Я получаю исключение, если не использовать время в формате «hh: mm: ss.fff». Есть ли способ указать другой шаблон и заставить работать «HH: mm»?Deserializing LocalTime от JSON с использованием JSON.NET и NodaTime приводит к NodaTime.Text.UnparsableValueException

Пожалуйста, смотрите этот код

using System; 
using System.Collections.Generic; 

using Newtonsoft.Json; 
using NodaTime; 
using NodaTime.Serialization.JsonNet; 
using NodaTime.Text; // Required for LocalTimePattern 
namespace TestNodaTime 
{ 
    class MyObject 
    { 
     [JsonProperty("var1")] 
     public int MyProperty { get; set; } 

     [JsonProperty("time")] 
     public LocalTime MyTime { get; set; } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      string serializedObject1 = "[{\"var1\":\"42\",\"time\":\"01:02:03.004\"}]"; 
      string serializedObject2 = "[{\"var1\":\"42\",\"time\":\"01:02\"}]"; 

      JsonSerializerSettings jss = new JsonSerializerSettings(); 
      jss.ConfigureForNodaTime(DateTimeZoneProviders.Bcl); 

      // This works - the pattern is "hh:mm:ss.fff" 
      MyObject mo1 = JsonConvert.DeserializeObject<List<MyObject>>(serializedObject1, jss)[0]; 

      // This causes an exception - the pattern is "HH:mm" 
      MyObject mo2 = JsonConvert.DeserializeObject<List<MyObject>>(serializedObject2, jss)[0]; 
      /* 
      * An unhandled exception of type 'NodaTime.Text.UnparsableValueException' occurred in Newtonsoft.Json.dll 
      * Additional information: The value string does not match a quoted string in the pattern. 
      * Value being parsed: '01:02^'. (^ indicates error position.) 
      */ 
     } 
    } 
} 

выбросу исключения:

 
NodaTime.Text.UnparsableValueException was unhandled 
    HResult=-2146233033 
    Message=The value string does not match a quoted string in the pattern. Value being parsed: '01:02^'. (^ indicates error position.) 
    Source=NodaTime 
    StackTrace: 
     at NodaTime.Text.ParseResult`1.GetValueOrThrow() 
     at NodaTime.Text.ParseResult`1.get_Value() 
     at NodaTime.Serialization.JsonNet.NodaPatternConverter`1.ReadJsonImpl(JsonReader reader, JsonSerializer serializer) 
     at NodaTime.Serialization.JsonNet.NodaConverterBase`1.ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer) 
     at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.DeserializeConvertable(JsonConverter converter, JsonReader reader, Type objectType, Object existingValue) 
     at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target) 
     at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id) 
     at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) 
     at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) 
     at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateList(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty containerProperty, String id) 
     at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue, String id) 
     at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) 
     at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent) 
     at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType) 
     at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType) 
     at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings) 
     at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings) 
     at TestNodaTime.Program.Main(String[] args) 
     at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) 
     at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) 
     at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() 
     at System.Threading.ThreadHelper.ThreadStart_Context(Object state) 
     at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) 
     at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) 
     at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 
     at System.Threading.ThreadHelper.ThreadStart() 
    InnerException: 
+0

Все версии являются «последними» стабильными версиями. –

ответ

6

Вам нужно удалить конвертеры по умолчанию он добавляет при вызове ConfigureForNodaTime. Эти конвертеры используют по умолчанию formats и не могут конфигурироваться (насколько я могу судить).

JsonSerializerSettings jss = new JsonSerializerSettings(); 
jss.ConfigureForNodaTime(DateTimeZoneProviders.Bcl); 

jss.Converters.Remove(NodaConverters.LocalTimeConverter); 
jss.Converters.Add(new NodaPatternConverter<LocalTime>(LocalTimePattern.CreateWithInvariantCulture("HH':'mm"))); 

MyObject mo2 = JsonConvert.DeserializeObject<List<MyObject>>(serializedObject2, jss)[0]; 
+1

Мне пришлось добавить: «используя NodaTime.Text». В противном случае, отлично. Благодаря! –

+0

@DavidRogers Я отменил редактирование из-за * незначительной * разницы в коде. Из [документации] (http://nodatime.org/1.2.x/userguide/text.html) - * где valid,: всегда относится к сепаратору времени, специфичному для культуры (двоеточие в культуре инвариантов) * - это означает, что запуск кода в локальном, где ':' был * note * разделителем времени, он не смог бы проанализировать. Указание '':'' означает, что мы ищем двоеточие, независимо от языка. – Rob

+0

Он также поддерживает соответствие шаблонам по умолчанию: https://github.com/nodatime/nodatime/blob/69a2cdad9cb4c32a82620eae4f2460ff9479570a/src/NodaTime/Text/LocalDateTimePattern.cs#L76 – Rob