2

私は 2 時間ずっと 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
4

2 に答える 2

5

とった!2つの秘密があります。1 つ目は、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());
}
于 2012-04-22T00:46:40.877 に答える
0

裏で何をしているのかはわかりませんが、コンストラクターで指定せずにNewtonsoft呼び出すと、 aがスローされます。new System.Uri("/about-us")UriKind.RelativeUriFormatException

そのため、Uri がモデルでどのように作成されているかによっては、保存する前にそれが絶対であることを確認することがオプションになる場合があります。

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

于 2012-04-21T15:05:59.133 に答える