Json.NET Uri(反序列化)错误 [英] Json.NET Uri (de)serialization errors

查看:91
本文介绍了Json.NET Uri(反序列化)错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I need to serialize and deserialize an object that contains an System.Uri property using the latest (4.0.3) Json.NET library.

以下代码演示了该问题:

The following code demonstrates the problem:

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.下可以正常工作.

The DeserializeObject method throws an JsonReaderException. This works fine with 4.0.2.

我已经在Codeplex上提交了一个问题,其中包含测试和补丁程序以解决该问题,但是作者发布固定版本似乎需要一点时间.

I've submitted an issue on codeplex with tests and patch to fix the issue, but it seems it takes a bit for the author to release a fixed version.

同时我可以做些什么(使用JsonSettings或其他方法)以使最新版本按预期工作?

Meanwhile is there anything i can do ( using JsonSettings or anything else ) to make the latest version work as expected?

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

A few options i have so far:

  1. 坚持使用4.0.2-新的nuget软件包取决于4.0.3
  2. 将uri更改为字符串-我宁愿使用选项1和手动管理的pkg依赖项
  3. 使用应用了补丁的自定义版本-这是我现在正在做的,但是我讨厌重写nuget包的程序集的想法.

推荐答案

您可以编写一个帮助器类,该类使用Uri.OriginalString属性来规避System.Uri的常规处理,并将其完全视为字符串.

You can write a helper class that circumvents the usual handling of System.Uri and treats it purely as a string, using the Uri.OriginalString property.

这是一个代码示例,它使用从Json.Net的JsonConverter派生的转换器类完全做到了这一点.

Here's a code sample that does exactly that with a converter class derived from Json.Net's JsonConverter.

OriginalString属性(System.Uri)@ MSDN

一个警告是,您必须更新使用JsonConvert的所有位置,以将帮助程序类包括为额外的JsonConverter参数之一.

One caveat is that you must update all places where you use JsonConvert to include the helper class as one of the extra JsonConverter parameters.

我还添加了一个示例,该示例使用Uri作为类中的成员变量,以说明不必覆盖类的属性,尽管它可能对您更方便.如果是这样,您可以将[JsonConverter(UriConverter)]用作需要它的成员的属性.

I've also added an example using Uri as a member variable in a class, to demonstrate that one wouldn't necessarily have to override the attributes on a class, though it might be more convenient for you. If so, you could use [JsonConverter(UriConverter)] as an attribute on members that need it.

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();
        }
    }
}

这篇关于Json.NET Uri(反序列化)错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆