2016-05-03 23 views
1

Wir haben Dokumente auf DocumentDB, die ein Datum auf ISO 8601 format speichern. Diese Daten werden als Strings gespeichert:Deaktivieren Sie DateParseHandling bei der Dokumentdeserialisierung

{ 
    "CreatedOn": "2016-04-15T14:54:40Z", 
    "Title": "Some title", 
    "id": "xxx-xxx-xxxx-xxx-xxx-xxx" 
} 

Wir verwenden die neueste Azure DocumentDB SDK (1.7.0) auf einem WebAPI, die ASP.NET-Core verwendet.

Die C# -Klasse, die unsere Dokumente abbildet, hat die Eigenschaft "CreatedOn" als Zeichenfolge.

public class Item 
{ 
    public string CreatedOn { get; set; } 

    public string id { get; set; } 

    public string Title { get; set; } 
} 

Das Problem ist, dass, wenn wir ein Dokument und das SDK deserialisiert sie lesen, versucht er es zu einem Datetime zu konvertieren und dann zurück zu einem String. Resultat:

{ 
    "CreatedOn": "15/04/2016 14:54:40", 
    "Title": "Some title", 
    "id": "xxx-xxx-xxxx-xxx-xxx-xxx" 
} 

Was ich brauche, ist mit dem SDK die Werte unangetastet zu verlassen. Ich habe versucht, die Standard-SerializerSettings zu setzen, um die Datumsanalyse zu vermeiden:

services.AddMvc().AddJsonOptions(opts => 
{ 
    opts.SerializerSettings.DateParseHandling = Newtonsoft.Json.DateParseHandling.None; 
}); 

Aber es hat nicht funktioniert.

Ich versuchte mit einem JsonConverter Attribut, aber das Problem ist, dass auf die ReadJson überschreiben Methode, der Leser bereits den String-Wert zu einem DateTime analysiert.

class StringJsonConverter : JsonConverter 
{ 
    public override bool CanConvert(Type objectType) 
    { 
     return true; 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     writer.WriteValue(value.ToString()); 
    } 

    public override bool CanRead 
    { 
     get { return true; } 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     reader.Value <-- already a parsed DateTime 
    } 
} 

Haben Sie Ideen, wie Sie dieses automatische Parsing überwinden können?

+0

Matias, ist dies ein WebAPI Zuordnungsproblem statt eines DocumentDB-Problems? Wenn Sie als Zeichenfolge speichern und als Zeichenfolge zurücklesen, führt das DocumentDB SDK keine Übersetzungen aus. –

+0

Hi @Aravind, dies ist ein DocumentDB-Problem. Das Ergebnis, das ich zeige, ist, wenn ich die Methode [CreateDocumentQuery] (https://msdn.microsoft.com/en-us/library/azure/microsoft.azure.documents.linq.documentqueryable.createdocumentquery.aspx) auf der SDK. DocumentDB verwendet Json.Net intern, das Problem ist, dass sie [die JsonSettings] nicht offen legen (https://feedback.azure.com/forums/263030-documentdb/suggestions/6422364-allow-me-to-set-jsonserializersettings) und Json.Net versucht automatisch, eine datumsähnliche Zeichenfolge zu einer DateTime zu analysieren, auch wenn die zugeordnete Klasse ein Zeichenfolgenattribut hat. –

+1

Die Einstellung [DateParseHandling] (http://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_DateParseHandling.htm) von Json.Net hat das Ziel, diese automatische Analyse-Logik zu deaktivieren, sie aber auf globaler Ebene zu setzen scheint keinen Einfluss darauf zu haben, wie DocumentDB es intern verwendet. –

Antwort

0

Schließlich eine Abhilfe gefunden, da die JsonSettings are not accesible zu dieser Zeit, ich bin ein JsonConverter mit:

public class StringJsonConverter : JsonConverter 
    { 
     public override bool CanConvert(Type objectType) 
     { 
      return true; 
     } 

     public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
     { 
      writer.WriteValue(value.ToString()); 
     } 

     public override bool CanRead 
     { 
      get { return true; } 
     } 

     public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
     { 
      if (reader.ValueType.Equals(typeof(DateTime))) 
      { 
       return ((DateTime)reader.Value).ToIso8601Date(); 
      } 
      if (reader.ValueType.Equals(typeof(DateTimeOffset))) 
      { 
       return ((DateTimeOffset)reader.Value).DateTime.ToIso8601Date(); 
      } 
      return (string)reader.Value; 
     }   
    } 

Mit dieser einfachen Erweiterung:

public static class DateTimeExtensions 
{ 
    private const string DateTimeFormat = "{0}-{1}-{2}T{3}:{4}:{5}Z"; 

    public static string ToIso8601Date(this DateTime date) 
    { 
     if (date.Equals(DateTime.MinValue)) 
     { 
      return null; 
     } 
     return string.Format(
      DateTimeFormat, 
      date.Year, 
      PadLeft(date.Month), 
      PadLeft(date.Day), 
      PadLeft(date.Hour), 
      PadLeft(date.Minute), 
      PadLeft(date.Second)); 
    } 
    private static string PadLeft(int number) 
    { 
     if (number < 10) 
     { 
      return string.Format("0{0}", number); 
     } 

     return number.ToString(CultureInfo.InvariantCulture); 
    } 
} 
Verwandte Themen