C# Json.NET Uri(反)序列化错误

C# Json.NET Uri(反)序列化错误,c#,serialization,json.net,deserialization,C#,Serialization,Json.net,Deserialization,我需要使用最新的(4.0.3)库序列化和反序列化包含System.Uri属性的对象 以下代码演示了该问题: string input = "http://test.com/%22foo+bar%22"; Uri uri = new Uri(input); string json = JsonConvert.SerializeObject(uri); Uri output = JsonConvert.DeserializeObject<Uri>(json); 字符串输入=”http:

我需要使用最新的(4.0.3)库序列化和反序列化包含System.Uri属性的对象

以下代码演示了该问题:

string input = "http://test.com/%22foo+bar%22";
Uri uri = new Uri(input);
string json = JsonConvert.SerializeObject(uri);
Uri output = JsonConvert.DeserializeObject<Uri>(json);
字符串输入=”http://test.com/%22foo+巴%22”;
Uri=新的Uri(输入);
字符串json=JsonConvert.SerializeObject(uri);
Uri输出=JsonConvert.DeserializeObject(json);
反序列化对象方法抛出一个JsonReaderException。这在4.0.2中运行良好

我已经在codeplex上提交了一个问题,其中包含了修复该问题的测试和补丁,但是作者发布一个修复版本似乎需要一些时间

同时,我能做些什么(使用JsonSettings或其他方法)使最新版本如预期的那样工作吗

到目前为止,我有几个选择:

  • 坚持4.0.2-新的nuget包依赖于4.0.3
  • 将uri更改为字符串-我宁愿使用选项1和手动管理的pkg依赖项
  • 使用应用补丁的自定义构建-这就是我现在要做的,但我讨厌覆盖nuget包的程序集

  • 您可以编写一个helper类,该类绕过通常对
    System.Uri
    的处理,并使用
    Uri.OriginalString
    属性将其纯粹视为字符串

    下面是一个代码示例,它使用一个从Json.Net的
    JsonConverter
    派生的转换器类来实现这一点

    需要注意的是,必须更新使用JsonConvert的所有位置,以将helper类作为额外的
    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();
            }
        }
    }
    
    使用Newtonsoft.Json;
    命名空间JsonUriSerializeTest
    {
    班级计划
    {
    公共类UriConverter:JsonConverter
    {
    公共覆盖布尔CanConvert(类型objectType)
    {
    返回objectType.Equals(typeof(Uri));
    }
    公共重写对象ReadJson(JsonReader阅读器,类型objectType,对象existingValue,JsonSerializer序列化程序)
    {
    if(reader.TokenType==JsonToken.String)
    {
    返回新的Uri((字符串)reader.Value);
    }
    if(reader.TokenType==JsonToken.Null)
    {
    返回null;
    }
    抛出新的InvalidOperationException(“UriConverter的未处理案例。检查此转换器是否应用于错误的序列化类型。”);
    }
    公共重写void WriteJson(JsonWriter编写器、对象值、JsonSerializer序列化器)
    {
    if(null==值)
    {
    WriteNull();
    返回;
    }
    if(值为Uri)
    {
    writer.WriteValue(((Uri)值).OriginalString);
    返回;
    }
    抛出新的InvalidOperationException(“UriConverter的未处理案例。检查此转换器是否应用于错误的序列化类型。”);
    }
    }
    公共类对
    {
    公共字符串标签{get;set;}
    公共Uri第一个{get;set;}
    公共Uri第二个{get;set;}
    公共空间显示()
    {
    WriteLine(string.Format(“label:{0}”,label));
    WriteLine(string.Format(“first:{0}”,first));
    WriteLine(string.Format(“second:{0}”,second));
    }
    }
    静态void Main(字符串[]参数)
    {
    字符串输入=”http://test.com/%22foo+巴%22”;
    Uri=新的Uri(输入);
    string json=JsonConvert.SerializeObject(uri,new UriConverter());
    Uri输出=JsonConvert.DeserializeObject(json,new UriConverter());
    控制台写入线(输入);
    Console.WriteLine(output.ToString());
    Console.WriteLine();
    UriPair=新的UriPair();
    pair.label=输入;
    pair.first=null;
    pair.second=新Uri(输入);
    字符串jsonPair=JsonConvert.SerializeObject(对,新的UriConverter());
    UriPair outputPair=JsonConvert.DeserializeObject(jsonPair,new UriconConverter());
    outputPair.Display();
    Console.WriteLine();
    Console.ReadKey();
    }
    }
    }
    
    谢谢你的回答。Json.NET的作者修复了这个问题,不幸的是,修复只会出现在下一个版本中。在此之前,如果可以,我将坚持使用4.0.2,如果不使用带有自定义转换器的4.0.3