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

标签 c# serialization json.net deserialization

我需要使用最新的 (4.0.3) Json.NET 序列化和反序列化包含 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);

DeserializeObject 方法抛出 JsonReaderException。这适用于 4.0.2。

我已经在 codeplex 上提交了一个带有测试和补丁的问题来修复这个问题,但是作者似乎需要一些时间才能发布一个固定版本。

与此同时,我可以做些什么(使用 JsonSettings 或其他任何东西)来使最新版本按预期工作吗?

目前我有几个选择:

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

最佳答案

您可以编写一个辅助类来绕过 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();
        }
    }
}

关于c# - Json.NET Uri(反)序列化错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7792382/

相关文章:

asp.net-mvc-3 - 使用 JSON.NET 作为 ASP.NET MVC 3 中的默认 JSON 序列化器 - 可能吗?

c# - 序列化/反序列化嵌套 POCO 属性,而不嵌套在 json.net 中

c# - WPF中干净而优雅的 View 模型

php - 使用 Json_encode 数据或序列化数据并存储在数据库中哪个更有效?

java - 了解序列化代理

c# - 从基类派生的类的 XmlSerializer 构造函数错误

c# - Json.NET反序列化为接口(interface)实现

c# - 运算符 '&' 不能应用于类型 'T' 和 'T' 的操作数

c# - 在C#中将double格式化为字符串

c# - 从线程返回一个值?