Json.Net - 从错误中获得价值的'System.Net.IPAddress'ScopeId“ [英] Json.Net - Error getting value from 'ScopeId' on 'System.Net.IPAddress'

查看:849
本文介绍了Json.Net - 从错误中获得价值的'System.Net.IPAddress'ScopeId“的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图与序列化的Json.Net对象IPEndpoint,我得到了以下错误:

I am trying to serialize an IPEndpoint object with Json.Net and I get the following error:

错误获取值从'ScopeId'对'System.Net。 ip地址。

Error getting value from 'ScopeId' on 'System.Net.IPAddress'.

该错误的原因是,我只使用在端点上的ip地址对象的IPV4属性。当JSON解析器试图解析IPv6的部分,它访问尝试的操作不支持引用的对象的类型,它抛出一个套接字异常ScopeID财产(空就足够了微软!)

The cause of the error is that I am only using the IPV4 properties of the IPAddress object in the endpoint. When the Json parser tries to parse the IPv6 portion, it accesses the ScopeID property which throws a socket exception "The attempted operation is not supported for the type of object referenced" (A null would have sufficed microsoft!)

我想知道是否有可能是相距超过一切翻录和编码的地址信息作为字符串这以外的解决方法吗?在某些时候,我确实想支持IPv6。有什么可以在Json.NET进行忽略错误或根本就没有尝试如果IPAddress家庭设置为网间而非InternetworkIPV6序列化ScopeID?

I was wondering if there may be a workaround for this other than ripping everything apart and coding the address information as a string? At some point I do want to support IPV6. Is there anything that can be done in Json.NET to ignore the error or simply NOT attempt to serialize the ScopeID if the IPAddress family is set to Internetwork instead of InternetworkIPV6?

谢谢,

Dinsdale

推荐答案

ip地址类不是系列化很友好,如您所见。它不仅将抛出一个 SocketException 如果您尝试访问 ScopeID 字段为IPv4地址,但它也将扔如果尝试直接访问地址字段IPv6地址!

The IPAddress class is not very friendly to serialization, as you've seen. Not only will it throw a SocketException if you try to access the ScopeID field for an IPv4 address, but it will also throw if you try to access the Address field directly for an IPv6 address!

要解决的异常,你将需要自定义 JsonConverter 。 A转换器允许你告诉Json.Net正是你想如何它序列化和/或反序列化一个特定类型的对象。对于 ip地址,似乎得到满足大家只是把它转换成字符串表示和回数据的最简单方法。我们能做到这一点的转换器。下面是我会怎么写:

To get around the exceptions, you will need a custom JsonConverter. A converter allows you to tell Json.Net exactly how you'd like it to serialize and/or deserialize a particular type of object. For an IPAddress, it seems the easiest way to get the data that satisfies everyone is simply to convert it to its string representation and back. We can do that in the converter. Here is how I would write it:

class IPAddressConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(IPAddress));
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        IPAddress ip = (IPAddress)value;
        writer.WriteValue(ip.ToString());
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JToken token = JToken.Load(reader);
        return IPAddress.Parse(token.Value<string>());
    }
}



很简单,因为这些事情。但是,这不是故事的结束。如果你需要去往返与 IPEndPoint ,那么你需要为它的转换器为好。为什么?因为 IPEndPoint 不包含默认构造函数,所以Json.Net将不知道如何进行实例化。幸运的是,该转换器并不难写或者:

Pretty straightforward, as these things go. But, this is not the end of the story. If you need to go round-trip with your IPEndPoint, then you will need a converter for it as well. Why? Because IPEndPoint does not contain a default constructor, so Json.Net will not know how to instantiate it. Fortunately, this converter is not difficult to write either:

class IPEndPointConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(IPEndPoint));
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        IPEndPoint ep = (IPEndPoint)value;
        writer.WriteStartObject();
        writer.WritePropertyName("Address");
        serializer.Serialize(writer, ep.Address);
        writer.WritePropertyName("Port");
        writer.WriteValue(ep.Port);
        writer.WriteEndObject();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject jo = JObject.Load(reader);
        IPAddress address = jo["Address"].ToObject<IPAddress>(serializer);
        int port = jo["Port"].Value<int>();
        return new IPEndPoint(address, port);
    }
}



所以,现在我们有转换器,怎么办我们使用它们?这里是一个演示了一个简单的例子程序。它首先创建了几个端点,使用自定义转换器,它们序列化为JSON,然后立即反序列化JSON回再次使用相同的转换器终端。

So, now that we have the converters, how do we use them? Here is a simple example program that demonstrates. It first creates a couple endpoints, serializes them to JSON using the custom converters, then immediately deserializes the JSON back into endpoints again using the same converters.

public class Program
{
    static void Main(string[] args)
    {
        IPEndPoint[] endpoints = new IPEndPoint[]
        {
            new IPEndPoint(IPAddress.Parse("8.8.4.4"), 53),
            new IPEndPoint(IPAddress.Parse("2001:db8::ff00:42:8329"), 81)
        };

        JsonSerializerSettings settings = new JsonSerializerSettings();
        settings.Converters.Add(new IPAddressConverter());
        settings.Converters.Add(new IPEndPointConverter());
        settings.Formatting = Formatting.Indented;

        string json = JsonConvert.SerializeObject(endpoints, settings);
        Console.WriteLine(json);

        IPEndPoint[] endpoints2 = 
            JsonConvert.DeserializeObject<IPEndPoint[]>(json, settings);

        foreach (IPEndPoint ep in endpoints2)
        {
            Console.WriteLine();
            Console.WriteLine("AddressFamily: " + ep.AddressFamily);
            Console.WriteLine("Address: " + ep.Address);
            Console.WriteLine("Port: " + ep.Port);
        }
    }
}

下面是输出:

[
  {
    "Address": "8.8.4.4",
    "Port": 53
  },
  {
    "Address": "2001:db8::ff00:42:8329",
    "Port": 81
  }
]

AddressFamily: InterNetwork
Address: 8.8.4.4
Port: 53

AddressFamily: InterNetworkV6
Address: 2001:db8::ff00:42:8329
Port: 81

这篇关于Json.Net - 从错误中获得价值的'System.Net.IPAddress'ScopeId“的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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