我一直在使用RavenDB两个小时,所以如果我错过了一些明显的东西,请道歉。
我正在使用System.Uri类型的属性存储非规范化视图模型。 Uri被序列化为一个字符串,我想这是可以的,但是当我加载文档时抛出这个异常:
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 :(得分:5)
知道了!有两个秘密。第一种是为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);
}
}
第二种方法是使用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());
}
答案 1 :(得分:0)
我不肯定Newtonsoft
在幕后做了什么,但如果它在构造函数中没有指定new System.Uri("/about-us")
而调用UriKind.Relative
,则会抛出UriFormatException
。< / p>
因此,根据您在模型中创建Uri的方式,您可以选择在存储之前确保它是绝对的。
我不是肯定的,但我认为像new System.Uri("http://foo.com/about-us")
这样的Uri会被存储为“http://foo.com/about-us”,并且会在它恢复时转换为OK。