Got a bit further, if I define a new ISocketJsonSerializer using the NewtonSoft JsonConvert class as a basis and define a custom converter for the XSockets Message class i can intercept the read of the json string e.g.
public class XsMessageJsonConverter : JsonConverter<Message>
{
public override bool CanWrite => false;
public override Message ReadJson(JsonReader reader, Type objectType, Message existingValue, bool hasExistingValue,
JsonSerializer serializer)
{
var jo = JObject.Load(reader);
var targetObj = Activator.CreateInstance(typeof(Message));
foreach (var prop in objectType.GetProperties()
.Where(p => p.CanRead && p.CanWrite))
{
var att = prop.GetCustomAttributes(true).OfType<JsonPropertyAttribute>().FirstOrDefault();
var jsonPath = (att != null ? att.PropertyName : prop.Name);
JToken token;
if (jsonPath == "Controller")
{
token = jo.SelectToken("C");
} else if (jsonPath == "Topic")
{
token = jo.SelectToken("T");
}
else
{
token = jo.SelectToken(jsonPath);
}
if (token != null && token.Type != JTokenType.Null)
{
var value = token.ToObject(prop.PropertyType, serializer);
prop.SetValue(targetObj, value, null);
}
}
return targetObj as Message;
}
public override void WriteJson(JsonWriter writer, Message value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
I can then include this in my custom serializer:
[Export(typeof(IXSocketJsonSerializer))]
public class CustomSerializer : IXSocketJsonSerializer
{
readonly JsonSerializerSettings _settings = new JsonSerializerSettings();
public CustomSerializer()
{
_settings.NullValueHandling = NullValueHandling.Ignore;
_settings.Converters.Add(new XsMessageJsonConverter());
}
// other methods omitted for bervity
public T DeserializeFromString<T>(string json)
{
var objT = JsonConvert.DeserializeObject<T>(json, _settings);
return objT;
}
public object DeserializeFromString(string json, Type type)
{
var obj = JsonConvert.DeserializeObject(json, type, _settings);
return obj;
}
}
Now with the above in place my server side controller code successfully decodes the string:
"{\"C\":\"catxsocketsmain\",\"T\":\"1\"}"
To a Message object with its Controller and Topic properties decoded to 'catsocketsmain' and '1' respectively.
Of course as I have not yet attempted to implement the write operation when Message is serialized to Json the full names are used e.g.
{
"Id":0,
"QoS":"FireAndForget",
"Retain":false,
"Data":"{"OrderNumber":1),
"MessageType":"Text",
"Controller":"catxsocketsmain",
"Topic":"catgeneralsocket"
}
which causes problems on the client.
In another approach I have been able to add the attribute:
[JsonConverter(typeof(StringEnumConverter))] to the enumerated type I rely on client side to be a string, with this in place I can get further by just using the native XSocket IXSocketJsonSerializer implementation,
I have other problems to investigate but i suspect sooner or later I will need to use the ServiceStack json serializer for some of our data payloads so inevitably i will need a custom implementation of IXSocketJsonSerializer.
Is the default implementation of this interface using a custom serializer to read and write the Message class? If anyone can provide a working example of a custom IXSocketJsonSerializer for the v5.8.0 preview it would be greatly appreciated.
thanks for reading
Gary