2011-10-17 67 views
2

我需要使用最新(4.0.3)Json.NET庫對包含System.Uri屬性的對象進行序列化和反序列化。Json.NET Uri(de)序列化錯誤

下面的代碼演示了此問題:

string input = "http://test.com/%22foo+bar%22"; 
Uri uri = new Uri(input); 
string json = JsonConvert.SerializeObject(uri); 
Uri output = JsonConvert.DeserializeObject<Uri>(json); 

的DeserializeObject方法拋出JsonReaderException。這適用於4.0.2。

我已經在codeplex上提交了一個關於測試和補丁來解決問題的問題,但是似乎需要一點時間讓作者發佈一個固定版本。

同時有什麼我可以做的(使用JsonSettings或其他)使最新版本按預期工作?

有幾個選項我到目前爲止有:

  1. 堅守4.0.2 - 新的NuGet軟件包依賴於4.0.3
  2. 變化URI字符串 - 我寧願用選項1,人工管理PKG去依賴關係
  3. 使用自定義生成與補丁應用 - 這是我現在正在做的,但我討厭重寫nuget包的程序集的想法。

回答

4

你可以寫一些規避的System.Uri通常的處理和純粹把它當作一個字符串,使用Uri.OriginalString屬性的輔助類。

下面是一個代碼示例,它與從Json.Net的JsonConverter派生的轉換器類完全相同。

OriginalString Property (System.Uri) @ MSDN

有一點需要注意的是,你必須更新在您使用JsonConvert包括輔助類的額外JsonConverter參數之一的所有地方。

我還添加了一個使用Uri作爲類中成員變量的示例,以證明不需要重寫某個類的屬性,儘管它可能對您更方便。如果是這樣,您可以使用[JsonConverter(UriConverter)]作爲需要它的成員的屬性。

using Newtonsoft.Json; 

namespace JsonUriSerializeTest 
{ 
    class Program 
    { 
     public class UriConverter : JsonConverter 
     { 
      public override bool CanConvert(Type objectType) 
      { 
       return objectType.Equals(typeof(Uri)); 
      } 

      public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
      { 
       if (reader.TokenType == JsonToken.String) 
       { 
        return new Uri((string)reader.Value); 
       } 

       if (reader.TokenType == JsonToken.Null) 
       { 
        return null; 
       } 

       throw new InvalidOperationException("Unhandled case for UriConverter. Check to see if this converter has been applied to the wrong serialization type."); 
      } 

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

       if (value is Uri) 
       { 
        writer.WriteValue(((Uri)value).OriginalString); 
        return; 
       } 

       throw new InvalidOperationException("Unhandled case for UriConverter. Check to see if this converter has been applied to the wrong serialization type."); 
      } 
     } 

     public class UriPair 
     { 
      public string label { get; set; } 
      public Uri first { get; set; } 
      public Uri second { get; set; } 

      public void Display() 
      { 
       Console.WriteLine(string.Format("label: {0}", label)); 
       Console.WriteLine(string.Format("first: {0}", first)); 
       Console.WriteLine(string.Format("second: {0}", second)); 
      } 
     } 

     static void Main(string[] args) 
     { 
      string input = "http://test.com/%22foo+bar%22"; 
      Uri uri = new Uri(input); 
      string json = JsonConvert.SerializeObject(uri, new UriConverter()); 
      Uri output = JsonConvert.DeserializeObject<Uri>(json, new UriConverter()); 

      Console.WriteLine(input); 
      Console.WriteLine(output.ToString()); 
      Console.WriteLine(); 

      UriPair pair = new UriPair(); 
      pair.label = input; 
      pair.first = null; 
      pair.second = new Uri(input); 
      string jsonPair = JsonConvert.SerializeObject(pair, new UriConverter()); 
      UriPair outputPair = JsonConvert.DeserializeObject<UriPair>(jsonPair, new UriConverter()); 

      outputPair.Display(); 
      Console.WriteLine(); 

      Console.ReadKey(); 
     } 
    } 
} 
+0

感謝您的回答。 Json.NET的作者解決了這個問題,不幸的是該修復只會在下一個版本中出現。直到那時,如果我可以堅持到4.0.2,如果不使用4.0.3與自定義轉換器 –