2013-09-07 21 views
24

Ben Json.NET ile IPEndPoint nesne seri çalışıyorum ve aşağıdaki hatayı alıyorum: 'danJson.Net - değer alma hatası üzerinde 'ScopeID' 'System.Net.IPAddress'

alınırken hata değeri ScopeId 'on' System.Net.IPAdres '.

Hatanın nedeni, yalnızca IPAddress nesnesinin IPV4 özelliklerini son noktada kullanıyorum olmasıdır. Json ayrıştırıcısı IPv6 bölümü ayrıştırmaya çalıştığında, bir yuva istisnası atar ScopeID özelliği erişir "Denenen işlem başvurulan nesnenin türü için desteklenmiyor" (Bir null olurdu, microsoft!)

bunun dışında her şeyi bir kenara bırakmak ve adres bilgisini bir ip olarak kodlamaktan başka bir çözüm olup olmadığını mı merak ediyorsunuz? Bir noktada IPV6'yı desteklemek istiyorum. IPaddress ailesi InternetworkIPV6 yerine Internet'e ayarlanmışsa, Jpe.NET'te hatayı görmezden gelebilecek veya ScopeID'i serileştirme girişiminde bulunmayacak bir şey var mı? gördüğünüz gibi

sayesinde

Dinsdale

cevap

45

IPAddress sınıf, serileştirme çok kolay değil. Bir IPv4 adresi için ScopeID alanına erişmeye çalışırsanız, yalnızca bir SocketException atmakla kalmaz, aynı zamanda bir IPv6 adresi için doğrudan Address alanına erişmeye çalışırsanız, bu özellik atılır.

Özel durumları aşmak için, özel bir JsonConverter'a ihtiyacınız olacak. Bir dönüştürücü, Json.Net'e tam olarak, belirli bir nesne türünü seri hale getirme ve/veya serileştirilmesini nasıl istediğinizi söylemenizi sağlar. Bir IPAddress için, herkese uygun verilerin basitçe onun dize temsili ve geri dönüşüme dönüştürülmesinin en kolay yolu görünüyor. Bunu dönüştürücüde yapabiliriz. İşte ben şöyle yazabilirim:

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

Oldukça basit, bu şeyler gittikçe. Ama bu hikayenin sonu değil. IPEndPoint ile gidiş-dönüş yapmanız gerekiyorsa, bunun için bir dönüştürücüye de ihtiyacınız olacaktır. Niye ya? IPEndPoint, varsayılan bir kurucu içermediğinden, Json.Net bunu nasıl başlatacağını bilmeyecektir.

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

Mademki artık dönüştürücüler var olduğunu, bunları nasıl kullanırım: Neyse ki, bu dönüştürücü ya yazmak zor değil mi? İşte gösteren basit bir örnek programdır. İlk önce birkaç bitiş noktası yaratır, bunları özel dönüştürücüler kullanarak JSON'a serer, ardından JSON'u aynı dönüştürücüleri kullanarak tekrar uç noktalara geri gönderir. İşte

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

çıktısı:

[ 
    { 
    "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 

Fiddle: WriteJson` çok `JObject` kullanılarak basitleştirilmiş olabilir` arasında https://dotnetfiddle.net/tK7NKY

+0

Kodu. – Athari

+0

Parlak. Çok teşekkür ederim Brian! – Dinsdale

+0

Sorun yok; yardım etmekten memnunum. –