2016-03-31 13 views
1

ile eksik özelliklerini ele ı bina olduğum bir proje için bir JSON Web Jetonu sınıfını yaptı:JSON Seri kaldırma: özel bir JsonConverter

[JsonObject] 
public class JwtPayload 
{ 
    [JsonProperty("iss", NullValueHandling = NullValueHandling.Ignore)] 
    public string Issuer { get; set; } = "https://mycompany.com/myIdentityServices"; 

    [JsonProperty("sub", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] 
    public string Subject { get; set; } 

. . . 

    [JsonProperty("nbf", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] 
    [JsonConverter(typeof(JsonUnixTimestampConverter))] 
    public DateTime? NotBefore { get; set; } = null; 

    [JsonProperty("iat", NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] 
    [JsonConverter(typeof (JsonUnixTimestampConverter))] 
    public DateTime? IssuedAt { get; set; } 

. . . 

} 

Şöyle Unix Damgası dönüşüm için bir JsonConverter vardır:

Belirteç serileştirme işlemi çok hızlı gerçekleştirilir ... Tam olarak beklediğim JSON'u alırım. Sorun, bir JSON belirtecini alıp "nbf" değerinin eksik olduğu bir JsonConvert.Deserialize<JwtPayload>("my JSON") yapmayı denediğimde, çok iyi geçmeyen bir Unix zaman damgası olarak "iat" ı ayrıştırmaya çalışırken serpantifikasyonum patlar. .

Açıkça benim JsonConverter sınıfımda bir sorunum var, ancak çevrimiçi gördüğüm neredeyse tüm örnekler, bir sınıfa bir dize değil, bir dizeye dönüştürülmesinden bahsediyor, bu yüzden yanlış yaptığımı anlamak zor. Birisi bana yardım edebilir mi?

NullValueHandling ve DefaultValueHandling farklı kombinasyonlarını denedim, bu yüzden sorunun JsonConverter sınıfında olduğunu düşünüyorum, ancak yanılıyor olabilirim.

cevap

1

Sorun şu ki, JsonReader.ReadAsString()Akıştan bir dize olarak sonraki JSON belirtecini okur.Geçerli JSON belirtecini bir dize olarak ayrıştırmak istiyorsunuz. Böylece:

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, 
     JsonSerializer serializer) 
    { 
     if (reader.TokenType == JsonToken.Null) 
     { 
      return GetDefault(objectType); 
     } 

     var text = (string)JToken.Load(reader); 
     return text.FromUnixTimestamp(); 
    } 

JsonReader.Value yerine (string)JToken.Load(reader) kullanarak okuyucu bu beklenenden daha karmaşık bir nesne durumunda cari değerinin sonunda konumlandırılmış edilmesini sağlar.

Tesadüfen, UNIX zaman damgalarını dizeleri olarak el ile ayırıp biçimlendiriyorsanız, bu değişkeni kültürde değil, değişmez kültürde yaptığınızdan emin olmalısınız. Ya da daha iyisi okuyup long yerine string olarak zaman damgalarını yazarak Json.NET sizin için yapalım:

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     var dt = value as DateTime?; 
     if (dt.HasValue) 
     { 
      writer.WriteValue(dt.Value.ToUnixTimestamp()); 
     } 
     else 
     { 
      writer.WriteNull(); 
     } 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, 
     JsonSerializer serializer) 
    { 
     if (reader.TokenType == JsonToken.Null) 
     { 
      return GetDefault(objectType); 
     } 

     var stamp = (long)JToken.Load(reader); 
     return stamp.FromUnixTimestamp(); 
    } 

public static class UnixTimeExtensions 
{ 
    const long SecondsToMilliseconds = 1000L; 
    const long MillisecondsToTicks = 10000L; 

    static readonly DateTime utcEpochStart = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); 

    public static DateTime FromUnixTimestamp(this long stamp) 
    { 
     return utcEpochStart.AddSeconds(stamp); 
    } 

    public static long ToUnixTimestamp(this DateTime dateTime) 
    { 
     var span = dateTime.ToUniversalTime() - utcEpochStart; 
     return span.Ticks/(SecondsToMilliseconds * MillisecondsToTicks); 
    } 
} 
+0

Mükemmel kullanarak, hile yaptığını. BTW, benim anlayışım unix zaman damgası 32 bitlik bir tamsayıdır, ancak bunu uzun süredir referansladınız. Anlayışım yanlış mı? –

+0

@JeremyHolovacs - .NET tarafında, zaman damgalarını her zaman güvenli olmak için "uzun" olarak gösteriyorum, çünkü 1) Bazen unix zaman damgası saniyeler yerine milisaniye olarak karşımıza çıkar, bunun için 'uzun' gereklidir ve 2) https://en.wikipedia.org/wiki/Year_2038_problem. – dbc

İlgili konular