2016-11-04 74 views
2

我有一個IP地址,我需要在我的代碼中有一個4字節的數組。不過,我想將它作爲字符串存儲在我的JSON設置文件中,格式如「192.168.0.1」。那麼我也想做相反的事情,並反序列化它。序列化字符串作爲字符串

我想這樣做,因爲我的Settings.json文件的目標是它是人爲可編輯的。

有沒有一種方法可以做到這一點?

我使用Newtonsoft JSON包

類我序列化

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

轉換方法我寫的。只是不知道在哪裏實施它們。

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

爲什麼不使用IPAddress類?它也有一個解析方法:https://msdn.microsoft.com/en-us/library/system.net.ipaddress.parse(v=vs.110).aspx – Greg

回答

1

你可以做一個custom JsonConverter像這樣:

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

你會然後將其附加到使用[JsonConverter(IPByteArrayConverter)]相應的屬性或字段:

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

樣品fiddle

更新

使用IPAddress的建議由@格雷格讓你的IPV6和IPV4支持。一個JsonConverter這種類型看起來像:

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

然後將其應用於Settings類和以前一樣,還是在JsonSerializerSettings.Converters全球範圍內使用它:

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

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

使用類:

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

樣品fiddle

+0

@ TheColonel26 - 答案更新與轉換爲@Greg建議的'IPAddress'類型 – dbc

+0

我正在考慮實現@ Greg的建議,但IPAddress.Parse方法有不良行爲,至少對於此實現。例如,如果輸入「65536」,則結果IP爲0.0.255.255。我寧願它不喜歡,除了這樣的條目。原因在於使用它的人不會期望這種行爲,並且只有這樣纔會進入這種行爲是錯誤的。 – TheColonel26