2016-11-04 20 views
2

私は自分のコードに4バイトの配列として必要なIPアドレスを持っています。しかし私はJSON設定ファイルに "192.168.0.1"のようなフォーマットの文字列として保存したいと思います。それから私は逆を行い、それを脱直列化したいと思う。バイト配列を文字列としてシリアル化する

私のSettings.jsonファイルの目標は人間が編集可能だからです。

これを行う方法はありますか?

は、私は私が書いた

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

コンバータ方式をシリアル化していますNewtonsoft JSONパッケージ

クラスを使用しています。ちょうどそれらを実装する場所がわからない。

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を使用しないのですか?また、Parseメソッドもあります。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のためにサポートして取得します。以前のようにSettingsクラスに適用します次に

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

、またはJsonSerializerSettings.Convertersでグローバルにそれを使用する:このタイプのJsonConverterは次のようになり

public class Settings 
{ 
    public string PLCIP; 
    public IPAddress RightTesterIP; 
    public IPAddress LeftTesterIP; 
} 
:クラスを使用して

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

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

サンプルfiddle

+0

@ TheColonel26 - @Gregによって提案された 'IPAddress'タイプ – dbc

+0

@Gregの提案を実装しようとしていましたが、IPAddress.Parseメソッドはこの実装のために少なくともat望ましくない動作をします。たとえば、 "65536"と入力すると、IPは0.0.255.255になります。私はむしろそのようなエントリを除いてはないでしょう。なぜなら、それを使用している人々がその行動を期待していないということと、そのようなものが入力される唯一の時間が間違っているからです。 – TheColonel26

関連する問題