2012-04-21 6 views
2

私は2時間のうちにRavenDBを使用してきました。シリアライズ/デシリアライズSystem.Uri

私はタイプのSystem.Uriの性質を持つ非正規化ビューモデルを格納しています。ウリは、私が推測OKである文字列としてシリアル化され、私はドキュメントを読み込むときに、この例外をスロー:

Message=Could not cast or convert from System.String to System.Uri. 
Source=Newtonsoft.Json 
StackTrace: 
    at Newtonsoft.Json.Utilities.ConvertUtils.EnsureTypeAssignable(Object value, Type initialType, Type targetType) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Utilities\ConvertUtils.cs:line 267 
    at Newtonsoft.Json.Utilities.ConvertUtils.ConvertOrCast(Object initialValue, CultureInfo culture, Type targetType) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Utilities\ConvertUtils.cs:line 244 
    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureType(JsonReader reader, Object value, CultureInfo culture, JsonContract contract, Type targetType) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 544 
+0

データベースでUriの外観はどうですか? – ataddeini

+0

"URL": "/ about-us" –

答えて

0

それがなくてnew System.Uri("/about-us")を呼び出している場合、私はカバーの下にやっていることNewtonsoftポジティブないんだけど、コンストラクタにUriKind.Relativeを指定すると、UriFormatExceptionがスローされます。

だから、あなたのウリは、あなたのモデルで作成されている方法に応じて、それはあなたがそれを格納する前に、絶対だ確実にするためのオプションであるかもしれません。

私は肯定的ではありませんが、new System.Uri("http://foo.com/about-us")のようなUriは "http://foo.com/about-us"として保存され、戻ってくるとOKに変換されると思います。

+0

私はまったく別の例外を得ています。スタックトレースと例外を見ると、Newtonsoftは単にビューモデルのSystem.Uriプロパティに文字列を割り当てようとしているようです。 –

5

ありがとうございました! 2つの秘密があります。最初に、UriタイプのJsonConverterを作成します。

public class UriJsonConverter : JsonConverter 
{ 

    public override bool CanConvert(Type objectType) 
    { 
     return object.Equals(objectType, typeof (Uri)); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     switch (reader.TokenType) 
     { 
      case JsonToken.String: 
       return CreateUri((string) reader.Value); 
      case JsonToken.Null: 
       return null; 
      default: 
       var msg = string.Format("Unable to deserialize Uri from token type {0}", reader.TokenType); 
       throw new InvalidOperationException(msg); 
     } 
    } 

    private static Uri CreateUri(string uriString) 
    { 
     Uri uri; 
     if (!Uri.TryCreate(uriString, UriKind.Absolute, out uri)) 
      if (!Uri.TryCreate(uriString, UriKind.Absolute, out uri)) 
       if (!Uri.TryCreate(uriString, UriKind.RelativeOrAbsolute, out uri)) 
       { 
        var msg = string.Format("Unable to determine proper UriKind for Uri {0}", uriString); 
        throw new InvalidOperationException(msg); 
       } 
     return uri; 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     if (null == value) 
     { 
      writer.WriteNull(); 
      return; 
     } 

     var uri = value as Uri; 
     if (uri != null) 
     { 
      writer.WriteValue(uri.OriginalString); 
      return; 
     } 
     var msg = string.Format("Unable to serialize {0} with {1}", value.GetType(), typeof (UriJsonConverter)); 
     throw new InvalidOperationException(msg); 
    } 

} 

第2は、RavenDBシリアライザにコンバータを登録することです。

private static DocumentStore OpenStore() 
{ 
    var store = new DocumentStore() 
        { 
         ConnectionStringName = "RavenDB" 
        }; 

    store.Conventions.CustomizeJsonSerializer = CustomJsonSerializer; 

    store.Initialize(); 
    return store; 
} 

private static void CustomJsonSerializer(JsonSerializer serializer) 
{ 
    serializer.Converters.Add(new UriJsonConverter()); 
} 
関連する問題