TheColonel26 TheColonel26 - 1 month ago 15
C# Question

Serialize byte array as string

I have an IP address that I need to have as a 4 byte array in my code. However I would like to store it in my JSON settings file as a string, formatted like "192.168.0.1". Then I would also like to do the reverse and deserialize it.

I'd like to do this as the goal of my Settings.json file is that it is human editable.

Is there a way I can do this?

I'm using the Newtonsoft JSON package

Class I am serializing

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


converter methods I wrote. Just not sure where to implement them.

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

dbc dbc
Answer

You could do it in a custom JsonConverter like so:

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

You would then attach it to the appropriate properties or fields using [JsonConverter(IPByteArrayConverter)]:

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

Sample fiddle.