2016-11-04 2 views
2

Ich habe eine IP-Adresse, die ich als 4-Byte-Array in meinem Code haben muss. Allerdings möchte ich es in meiner JSON-Einstellungsdatei als eine Zeichenfolge speichern, die wie "192.168.0.1" formatiert ist. Dann würde ich auch gerne das Gegenteil machen und es deserialisieren.Serialize Byte-Array als Zeichenfolge

Ich möchte dies als das Ziel meiner Settings.json-Datei ist, dass es menschlich editierbar ist.

Gibt es eine Möglichkeit, das kann ich tun?

Ich bin mit dem Newtonsoft JSON Paket

Klasse I

public class Settings 
{ 
    public string PLCIP; 
    public byte[] RightTesterIP; 
    public byte[] LeftTesterIP; 
} 

Konverter Methoden, die ich schrieb am Serialisierung. Ich bin mir nicht sicher, wo ich sie umsetzen soll.

private string ConvertIPByteArraytoString(byte[] ip) 
{ 
    StringBuilder builder = new StringBuilder(); 

    builder.Append(ip[0]); 

    for (int i = 1; i < ip.Length; i++) 
    { 
     builder.Append("."); 
     builder.Append(ip[i]); 

    } 
    return builder.ToString(); 
} 

private byte[] ConvertIPStringToByteArray(string ip, string ParameterName) 
{ 
    var blah = new byte[4]; 

    var split = ip.Split('.'); 

    if (split.Length != 4) 
    { 
     //Log.Error("IP Address in settings does not have 4 octets.Number Parsed was {NumOfOCtets}", split.Length); 
     //throw new SettingsParameterException($"IP Address in settings does not have 4 octets. Number Parsed was {split.Length}"); 
    } 

    for(int i = 0; i < split.Length; i++) 
    { 
     if(!byte.TryParse(split[i], out blah[i])) 
     { 
      //var ex = new SettingsParameterException($"Octet {i + 1} of {ParameterName} could not be parsed to byte. Contained \"{split[i]}\""); 
      //Log.Error(ex,"Octet {i + 1} of {ParameterName} could not be parsed to byte. Contained \"{split[i]}\"", i, ParameterName, split[i]); 
      //throw ex; 
     } 

    } 

    return blah; 
} 
+2

Warum nicht die Klasse IPAddress verwenden? Es hat auch eine Parse-Methode: https://msdn.microsoft.com/en-us/library/system.net.ipaddress.parse(v=vs.110).aspx – Greg

Antwort

1

Man könnte es wie so in einem custom JsonConverter tun:

public class IPByteArrayConverter : JsonConverter 
{ 
    private static string ConvertIPByteArraytoString(byte[] ip) 
    { 
     StringBuilder builder = new StringBuilder(); 

     builder.Append(ip[0]); 

     for (int i = 1; i < ip.Length; i++) 
     { 
      builder.Append("."); 
      builder.Append(ip[i]); 

     } 
     return builder.ToString(); 
    } 

    private static byte[] ConvertIPStringToByteArray(string ip) 
    { 
     var blah = new byte[4]; 

     var split = ip.Split('.'); 

     if (split.Length != 4) 
     { 
      //Log.Error("IP Address in settings does not have 4 octets.Number Parsed was {NumOfOCtets}", split.Length); 
      //throw new SettingsParameterException($"IP Address in settings does not have 4 octets. Number Parsed was {split.Length}"); 
     } 

     for (int i = 0; i < split.Length; i++) 
     { 
      if (!byte.TryParse(split[i], out blah[i])) 
      { 
       //var ex = new SettingsParameterException($"Octet {i + 1} of {ParameterName} could not be parsed to byte. Contained \"{split[i]}\""); 
       //Log.Error(ex,"Octet {i + 1} of {ParameterName} could not be parsed to byte. Contained \"{split[i]}\"", i, ParameterName, split[i]); 
       //throw ex; 
      } 

     } 

     return blah; 
    } 

    public override bool CanConvert(Type objectType) 
    { 
     throw new NotImplementedException(); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     if (reader.TokenType == JsonToken.Null) 
      return null; 
     var token = JToken.Load(reader); 
     if (token.Type == JTokenType.Bytes) 
      return (byte[])token; 
     return ConvertIPStringToByteArray((string)token); 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     var bytes = (byte[])value; 
     writer.WriteValue(ConvertIPByteArraytoString(bytes)); 
    } 
} 

Sie würden dann in die entsprechenden Eigenschaften befestigen oder Felder mit [JsonConverter(IPByteArrayConverter)]:

public class Settings 
{ 
    public string PLCIP; 
    [JsonConverter(typeof(IPByteArrayConverter))] 
    public byte[] RightTesterIP; 
    [JsonConverter(typeof(IPByteArrayConverter))] 
    public byte[] LeftTesterIP; 
} 

Probe fiddle.

aktualisieren

IPAddress Verwendung wie von @ Greg Sie für IPV6 unterstützt wird sowie IPV4. Ein JsonConverter für diese Art würde wie folgt aussehen:

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

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     if (reader.TokenType == JsonToken.Null) 
      return null; 
     var token = JToken.Load(reader); 
     if (token.Type == JTokenType.Bytes) 
     { 
      var bytes = (byte[])token; 
      return new IPAddress(bytes); 
     } 
     else 
     { 
      var s = (string)token; 
      return IPAddress.Parse(s); 
     } 
    } 

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

Dann wenden sie auf die Settings Klasse nach wie vor oder es weltweit nutzen in JsonSerializerSettings.Converters:

var jsonSettings = new JsonSerializerSettings 
{ 
    Converters = new [] { new IPAddressConverter() }, 
}; 

var json = JsonConvert.SerializeObject(settings, jsonSettings); 

die Klasse verwenden:

public class Settings 
{ 
    public string PLCIP; 
    public IPAddress RightTesterIP; 
    public IPAddress LeftTesterIP; 
} 

Probe fiddle.

+0

@ TheColonel26 - Antwort mit einem Konverter für die aktualisiert 'IPAddress' Typ vorgeschlagen von @Greg – dbc

+0

Ich habe versucht, @ Gregs Vorschlag zu implementieren, aber die IPAddress.Parse-Methode hat ein unerwünschtes Verhalten, zumindest für diese Implementierung. Zum Beispiel, wenn Sie "65536" eingeben, ergibt dies eine IP von 0.0.255.255. Ich würde es lieber nicht machen außer einem solchen Eintrag. Der Grund dafür ist, dass die Leute, die es benutzen, dieses Verhalten nicht erwarten und dass das einzige Mal, dass so etwas eintreten würde, irrtümlich ist. – TheColonel26