2

I have a case where the ServiceStack JSON serializer fails to deserialize, and where Newtonsoft's JSON.NET manages to do so. I have not found a clear-cut way to replace the default serializer with JSON.NET, so its global and for all classes.

JsConfig<T>.SerializeFn I guess works, but it is per class, and I want for all classes, globally.

How do I do that?

Background

I am using the ServiceStack.Messaging.Redis and Redis as an MQ solution. We use this approach to sending messages:

using (var mqClient = MqClientFactory.Instance.CreateMessageQueueClient())
{

    var uniqueCallbackQ = "mq:c1" + ":" + Guid.NewGuid().ToString("N");
    var clientMsg = new Message<TRequest>(request)
    {
        ReplyTo = uniqueCallbackQ
    };

    mqClient.Publish(clientMsg);
    //Blocks thread on client until reply message is received
    responseMessage = mqClient.Get<TResponse>(uniqueCallbackQ, timeout);
}

and for receiving message, standard stuff:

redisMqServer.RegisterHandler<TheRequest>(base.ExecuteMessage);

Simplified, I have a Request class that contains a public object Result {get; set;}, and this property is deserialized in ServiceStack as a Dictionary<string, object>, and not to the correct Type.

I am well aware of the recommendation to use strongly typed object, but my problem is we are not actually dealing with clean DTOs for external communication, but internal communication of internal objects, relying heavily on polymorphism and it legacy code, we are not creating new stuff right now.

So, in some cases, we have the "object" properties, and it doesn't work to deserialize it with ServiceStack. The Type info is there, so I assumed it would work, but it didn't (I have removed namespaces below for clarity):

string ssJson = ServiceStack.Text.JsonSerializer.SerializeToString(getTextMessageTemplateObject);

// above produces: 

{
    "_Type": "Deviation",
    "Result": [{
            "__type": "TextMessageTemplate, AlfaCommons",
            "_Message": "test",
            "_Type": "Deviation",
        }
    ],
    "Success": true,
}

// And then, deserialize the json above:

GetTextMessageTemplate ssGetTextMessageTemplate = ServiceStack.Text.JsonSerializer.DeserializeFromString< 
GetTextMessageTemplate>(ssJson);

This is the ssGetTextMessageTemplate (please note I removed some properties for clarity):

enter image description here

The Result prop was not deserialized correctly, as can be seen above.

When using JSON.NET, the serialized JSON is:

{
    "$type": "GetTextMessageTemplate, AlfaCommons",
    "_Type": 4,
    "Result": {
        "$type": "System.Collections.Generic.List`1[[TextMessageTemplate, AlfaCommons]], System.Private.CoreLib",
        "$values": [{
                "$type": "TextMessageTemplate, AlfaCommons",
                "_Message": "test",
                "_Type": 4,
            }
        ]
    }
}

and after deserializing, it works as expected:

enter image description here

So, I'd like to try the JSON.NET serializer in the case above instead.

halfer
  • 19,824
  • 17
  • 99
  • 186
Ted
  • 19,727
  • 35
  • 96
  • 154
  • Hi Ted. Could I ask you to install and use an English spell-checker for your posts? There are usually quite a few errors, and we don't have enough volunteer editors to keep repairing them. Stack Overflow is intended to be a long-term resource of questions and answers, rather than a chat-room, so longevity of material is important to us. – halfer Aug 22 '20 at 12:07
  • Hello. I'm sorry, but the edits you made are of cosmetic nature, and doesn't add anything really. "Didnt" or didn't? That isn't really something I find relevant, it is perfectly clear what I'm writing. Also, my English is pretty good, not being native speaker and all. Compared to many other posts here, my written English is pretty decent. I'm sure your time can be better spent than changing didnt to didn't. Thank you. – Ted Aug 23 '20 at 13:18
  • You can expect these edits to be made here, Ted. As I say, there is a simple solution - using a spell-checker is not too much too ask. – halfer Aug 23 '20 at 13:42

1 Answers1

0

ServiceStack.Redis has a hard dependency on ServiceStack.Text for its object Serialization, it doesn't support global substitution to use an alternative JSON Serailizer.

One workaround for sending arbitrary payloads in messages is to send a serialized JSON in a string Result property, which you could use JSON.NET to de/serialize.

Another potential workaround is using the FromObjectDictionary Reflection Utils to convert the Object Dictionary back into the typed DTO, e.g:

var result = objDictionary.FromObjectDictionary(theResultType);
mythz
  • 141,670
  • 29
  • 246
  • 390
  • How about [StackexchangeRedisExtensions](https://imperugo.gitbook.io/stackexchange-redis-extensions/usage/custom-serializer)? – TheMah Feb 06 '23 at 15:39