Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/297.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Json.Net-从';ScopeId';在';System.Net.IPAddress';_C#_.net_Json.net_System.net - Fatal编程技术网

C# Json.Net-从';ScopeId';在';System.Net.IPAddress';

C# Json.Net-从';ScopeId';在';System.Net.IPAddress';,c#,.net,json.net,system.net,C#,.net,Json.net,System.net,我试图用Json.Net序列化IPEndpoint对象,但出现以下错误: 从“System.Net.IPAddress”上的“ScopeId”获取值时出错 错误的原因是我只在端点中使用IPAddress对象的IPV4属性。当Json解析器尝试解析IPv6部分时,它会访问ScopeID属性,该属性引发套接字异常“所引用对象的类型不支持尝试的操作”(如果为null,microsoft就足够了!) 我想知道除了把所有的东西都撕成碎片并将地址信息编码为字符串之外,是否还有其他解决方法?在某种程度上,我确

我试图用Json.Net序列化IPEndpoint对象,但出现以下错误:

从“System.Net.IPAddress”上的“ScopeId”获取值时出错

错误的原因是我只在端点中使用IPAddress对象的IPV4属性。当Json解析器尝试解析IPv6部分时,它会访问ScopeID属性,该属性引发套接字异常“所引用对象的类型不支持尝试的操作”(如果为null,microsoft就足够了!)

我想知道除了把所有的东西都撕成碎片并将地址信息编码为字符串之外,是否还有其他解决方法?在某种程度上,我确实希望支持IPV6。如果IPAddress系列设置为Internetwork而不是InternetworkIPV6,那么在Json.NET中是否可以忽略该错误,或者干脆不尝试序列化ScopeID

谢谢


正如您所看到的,
IPAddress
类对序列化不是很友好。如果您尝试访问IPv4地址的
ScopeID
字段,它不仅会抛出
SocketException
,而且如果您尝试直接访问IPv6地址的
address
字段,它还会抛出

要绕过异常,您需要一个自定义的
JsonConverter
。转换器允许您准确地告诉Json.Net您希望它如何序列化和/或反序列化特定类型的对象。对于
IPAddress
,似乎获得满足所有人的数据的最简单方法就是将其转换为字符串表示形式并返回。我们可以在转换器中这样做。我会这样写:

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

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

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        return IPAddress.Parse((string)reader.Value);
    }
}
这些事情都很简单。但是,这并不是故事的结局。如果您需要使用
IPEndPoint
往返,则还需要一个转换器。为什么?因为
IPEndPoint
不包含默认构造函数,所以Json.Net不知道如何实例化它。幸运的是,该转换器也不难编写:

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;
        JObject jo = new JObject();
        jo.Add("Address", JToken.FromObject(ep.Address, serializer));
        jo.Add("Port", ep.Port);
        jo.WriteTo(writer);
    }

    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 = (int)jo["Port"];
        return new IPEndPoint(address, port);
    }
}

小提琴:

WriteJson的代码也可以使用JObject简化。我对这一点印象深刻。谢谢,你帮我省了不少时间。
public class Program
{
    static void Main(string[] args)
    {
        var endpoints = new IPEndPoint[]
        {
            new IPEndPoint(IPAddress.Parse("8.8.4.4"), 53),
            new IPEndPoint(IPAddress.Parse("2001:db8::ff00:42:8329"), 81)
        };

        var 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);

        var 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