Deserialise byte[] to generic type

I’m writing a custom implementation IAppSetting. The source of the config settings returns a byte[] Value.

Is there a hook into the deserialisation where, instead of serialising this to a byte[] I serialise it to a type T? Ideally I want the DTO returned by the config source to be:

public class KeyValue<T>
{
  public string Key { get; set; }
  public T Value { get; set; }
}

Which would allow IAppSettings.Get<T> or .GetString() to deserialise to KeyValue<T> or KeyValue<string> respectively. One thing I have looked at is having something like the following, but this doesn’t seem as clean.

public class KeyValue<T>
{
  public string Key { get; set; }
  public byte[] Value { get; set; }

  public T GetValueAs<T>(){  //return Value as T }
}

I also looked into JsConfig<> but this isn’t usable as T is unknown. Any suggestions/pointers welcome!

Thanks

I’m not following, IAppSettings doesn’t contain any byte[] API’s. The Get<T> method is just a generic API saying what your provider should attempt to deserialize the Config Setting into, it’s up to your provider’s implementation on how they should deserialize it into that type.

The default AppSettingsBase implementation uses the JSV Format since it’s lack of double-quotes by default makes it more optimal to use for use in configuration. But it’s up to your IAppSettings provider what format to store it as and what it supports deserializing into.

The JSON and JSV Format are text based formats so their configuration values are maintained as strings, if you’re storing strings as UTF8 bytes you can convert them into strings using the FromUtf8Bytes() extension method, i.e:

string text = bytes.FromUtf8Bytes();

Likewise you can convert strings into UTF8 bytes with:

byte[] bytes = text.ToUtf8Bytes();

But otherwise I’m not sure what you’re looking for, if you’re storing values in a different binary format you’ll need to handle the deserialization yourself and what Types your provider can support will be limited by the binary format you use.

Sorry, I’ve re-read my initial question and it’s not the clearest.

The fact I’m implementing IAppSettings isn’t really relevant to the overall question and may have muddied the waters slightly. The issue I’m having is that I have a DTO and use it to call a service (not a ServiceStack service, an external REST service) that returns data as byte[] and I’m wondering how I can nicely handle the deserialization of that into my DTO.

I’ve got it working with:

public class KeyValue
{
  public string Key { get; set; }

  public byte[] Value { get; set; }
    
  public T GetValue<T>()
  {
    return TypeSerializer.DeserializeFromString<T>(Value.FromUtf8Bytes());
  }
}

But I’m curious to know if I could setup deserialization to allow me to do away with the GetValue<T> method and instead have:

public class KeyValue<T>
{
  public string Key { get; set; }
  public T Value { get; set; }
}

Hope that makes more sense!?

No doesn’t change much, what’s byte[] holding?

From your GetValue<T> implementation it looks like it’s just holding UTF8 bytes of a serialized JSV string? In which case byte[] is not important, you can convert it to a string:

string jsv = bytes.FromUtf8Bytes();

Then you can convert it back to what the JSV was serialized into. But KeyValue<T> is a generic type definition it’s not a Type, i.e. a Serializer isn’t going to know what concrete type to deserialize into. What was the code you used to serialize to byte[] in the first place?

byte[] is holding an encoded blob of data that is returned from the backing config store I’m using.

Yes that’s correct, the GetValue<T> implementation is just deserializing the bytes.

I am using Service Stack http utils to get the KeyValue object holding the byte[]:

theUrl.GetJsonFromUrl().FromJson<KeyValue>();

I’m using .FromJson() as the consul request returns JSON. This JSON has a “Value” field which contains an encoded blob of JSV data that I have saved.

What I was wondering is if I could have something like theUrl.GetJsonFromUrl().FromJson<KeyValue<CustomType>>(); which would save me storing the byte[] and having the separate GetValue<T> method?

If it can’t be done then what I have is working, I was just wondering if this is possible as it would be a bit cleaner.

I still feel like what I’m asking isn’t as clear as it should be.

In essence I’m making a call and getting back some JSON:

{ "Key": "person", "Value": "e0FnZTo5OSxOYW1lOlRlc3QgUGVyc29ufQ==" }

The value is a base-64 encoded blob of data (in this case JSV: {Age:99,Name:Test Person}).

How can I control deserialisation of this to KeyValue<T>, e.g. KeyValue<Person>?

1 Like

To be clear what you have here:

{ "Key": "person", "Value": "e0FnZTo5OSxOYW1lOlRlc3QgUGVyc29ufQ==" }

Is 3 levels of encoding, i.e. a JSON string with a byte[] Value property that is encoded in Base64 so it’s safe to hold in text-based format, which then holds a serialized JSV DTO.

So a serialized text-based format holding Base64 binary encoded data of another serialization format. You need to reverse the encoding in order to access the serialized data. First to access the raw value you need to first decode the JSON:

var keyValue = json.FromJson<KeyValue<byte[]>>();

Then you need to convert the byte[] back into a UTF8 string:

var jsv = keyValue.Value.FromUtf8Bytes();
jsv.Print(); //= {Age:99,Name:Test Person}

Which you can then deserialize into the original Person dto:

var person = jsv.FromJson<Person>();