2017-02-20 99 views
1

我試圖使用NodaTime來解釋從第三方API檢索的日期。日期進來的格式在相同的響應,一個我特別遇到的麻煩討厭的陣列是類似於:如何反序列化同一個JSON對象中的不同NodaTime LocalDate模式

{ 
    "ShortDate": "2017-01-01", 
    "LongDate": "01 January 2017" 
} 

我可以正確deserialise一種格式或另一種使用NodaPatternConverter,但不能同時使用。

一個簡單的例子示出的問題是這樣的:

using Newtonsoft.Json; 
using NodaTime; 
using NodaTime.Serialization.JsonNet; 
using NodaTime.Text; 

namespace NodaLocalDateConverterTest 
{ 
    class ExampleDatedModel 
    { 
     public LocalDate ShortDate { get; set; } 

     public LocalDate LongDate { get; set; } 
    } 


    class Program 
    { 
     static void Main(string[] args) 
     { 
      var exampleJsonString = 
@"{ 
    ""ShortDate"": ""2017-01-01"", 
    ""LongDate"": ""01 January 2017"" 
}"; 

      var serialisationSettings = new JsonSerializerSettings(); 
      //NodaTime default converter supports ShortDate format 
      serialisationSettings.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb); 

      //Exception on LongDate property 
      var deserialisedExample1 = JsonConvert.DeserializeObject<ExampleDatedModel>(exampleJsonString, serialisationSettings); 

      serialisationSettings.Converters.Remove(NodaConverters.LocalDateConverter); 
      serialisationSettings.Converters.Add(new NodaPatternConverter<LocalDate>(LocalDatePattern.CreateWithInvariantCulture("dd MMMM yyyy"))); 

      //Exception on ShortDate property 
      var deserialisedExample2 = JsonConvert.DeserializeObject<ExampleDatedModel>(exampleJsonString, serialisationSettings); 
     } 
    } 
} 

使用默認串行器給出拋出異常上的longdate屬性:

類型的未處理的異常「NodaTime.Text .UnparsableValueException'發生在 Newtonsoft.Json.dll

附加信息:值字符串不匹配requi來自格式字符串「yyyy」的紅色 數字。正在分析的值:'2017年1月1日 2017'。 (^表示錯誤位置。)

與自定義模式轉換器更換上ShortDate屬性會引發異常:

的類型 「NodaTime.Text.UnparsableValueException」未處理的異常發生在 Newtonsoft .Json.dll

附加信息:值字符串與格式字符串「」中的簡單 字符不匹配。正在解析的值:'20^17-01-01'。 (^指示錯誤位置。)

原則上,我認爲我可以使用兩個不同的轉換器兩個屬性,如

class ExampleDatedModel 
{ 
    [JsonConverter(typeof(ShortDateConverter)] 
    public LocalDate ShortDate { get; set; } 

    [JsonConverter(typeof(LongDateConverter)] 
    public LocalDate LongDate { get; set; } 
} 

但是我不明白如何使用NodaTime的NodaPatternConverter與該屬性,因爲你不能用模式實例化轉換器。

documentation有用地說:「自定義轉換器可以使用NodaPatternConverter從模式輕鬆創建。」但沒有舉例!

可能的解決方案我已經雖然大約是

  • 創建一對從NodaPatternConverter衍生轉換器,其被配置爲用於在兩個模式。
    • NodaPatternConverter是密封的,所以不能繼承。
  • 創建一對從JsonConverter衍生對付兩個模式
    • 轉換器我想這些會打電話與國內不同的圖案LocalDatePattern.Parse的兩個版本。
    • 整個JsonConverter的重新實現似乎有點過分。
  • 將日期反序列化爲字符串,然後再轉換日期。
    • 需要實現每類具有混合類型的類。
    • 使通用方法從API獲取資源更加複雜。

但我希望我只是缺少標記了資源類利用現有的轉換器的一種方式。

回答

2

這似乎確實是我們沒有考慮過的用例。對於「正常」使用,密封NodaPatternConverter感覺像是正確的方法 - 但是當JsonConverter必須由類型指定而不是實例化時,密封是令人沮喪的。我已經在filed an issue中解決了這個問題,我希望在下個月左右發佈。 (這是now implemented - 拉入請求顯示樣品的使用爲好。)

但是,同時我可能會只是NodaPatternConverter - 並添加註釋說這是隻有在那裏,直到你可以使用2.0。

您可能希望稍微修剪一下,因爲您可能不需要額外的驗證,假設您控制所有要序列化數據的代碼 - 如果您不需要擔心非ISO LocalDate值,你可能不需要驗證。

另一方面是,如果你只用解析使用轉換器,你根本不需要寫入方面 - 你可能現在只需要拋出一個異常。

開封NodaPatternConverter的替代方法是有一個簡單的(抽象的)DelegatingConverterBase類型,它代表另一個JsonConverter。典型用法是這樣的:

public sealed class ShortDateConverter : DelegatingConverterBase 
{ 
    public ShortDateConverter() : base(NodaConverters.LocalDate) {} 
} 

這可能是關注一個更優雅的分離 - 和可實施的用更少的代碼,直到它的野田時間的一部分,太:

public abstract class DelegatingConverterBase : JsonConverter 
{ 
    private readonly JsonConverter original; 

    protected DelegatingConverterBase(JsonConverter original) 
    { 
     this.original = original; 
    } 

    public override void WriteJson(
     JsonWriter writer, object value, JsonSerializer serializer) => 
     original.WriteJson(writer, value, serializer); 

    public override object ReadJson(
     JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) => 
     original.ReadJson(reader, objectType, existingValue, serializer); 

    public override bool CanRead => original.CanRead; 

    public override bool CanWrite => original.CanWrite; 

    public override bool CanConvert(Type objectType) => original.CanConvert(objectType); 
} 
+0

感謝多多考慮那。我可能會想出一些相同的東西,但不那麼優雅! – Xcodo

+0

@Xcodo:我很高興我最終不需要開封'NodaPatternConverter'。就分離關注而言,我絕對更喜歡這一點。我想知道爲什麼在Json.NET本身中沒有這樣的東西... –

相關問題