Serializzatore JSON ServiceStack: come posso modificare il serializzatore predefinito a livello globale?
Ho un caso in cui il serializzatore JSON di ServiceStack non riesce a deserializzare e in cui JSON.NET di Newtonsoft riesce a farlo. Non ho trovato un modo chiaro per sostituire il serializzatore predefinito con JSON.NET, quindi è globale e per tutte le classi.
JsConfig<T>.SerializeFn
Immagino funzioni, ma è per classe e voglio per tutte le classi, a livello globale.
Come lo faccio?
Sfondo
Sto usando ServiceStack.Messaging.Redis
e Redis come soluzione MQ. Utilizziamo questo approccio per l'invio di messaggi:
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);
}
e per ricevere messaggi, roba standard:
redisMqServer.RegisterHandler<TheRequest>(base.ExecuteMessage);
Semplificato, ho una classe Request che contiene un public object Result {get; set;}
e questa proprietà è deserializzata in ServiceStack come Dictionary<string, object>
e non nel tipo corretto.
Sono ben consapevole della raccomandazione di utilizzare oggetti fortemente tipizzati, ma il mio problema è che in realtà non abbiamo a che fare con DTO puliti per la comunicazione esterna, ma comunicazione interna di oggetti interni, facendo molto affidamento sul polimorfismo e sul suo codice legacy, non stiamo creando nuovi roba adesso.
Quindi, in alcuni casi, abbiamo le proprietà "oggetto" e non funziona per deserializzarlo con ServiceStack. Le informazioni sul tipo sono presenti, quindi ho pensato che avrebbe funzionato, ma non è stato così (ho rimosso gli spazi dei nomi di seguito per chiarezza):
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);
Questo è ssGetTextMessageTemplate
(si prega di notare che ho rimosso alcune proprietà per chiarezza):

Il prop Result non è stato deserializzato correttamente, come si può vedere sopra.
Quando si utilizza JSON.NET, il JSON serializzato è:
{
"$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,
}
]
}
}
e dopo la deserializzazione, funziona come previsto:

Quindi, mi piacerebbe provare invece il serializzatore JSON.NET nel caso sopra.
Risposte
ServiceStack.Redis ha una forte dipendenza da ServiceStack.Text per la serializzazione degli oggetti, non supporta la sostituzione globale per utilizzare un Serailizer JSON alternativo.
Una soluzione alternativa per l'invio di payload arbitrari nei messaggi consiste nell'inviare un JSON serializzato in una string Result
proprietà, che è possibile utilizzare JSON.NET per de/serializzare.
Un'altra potenziale soluzione consiste nell'utilizzare FromObjectDictionary Reflection Utils per riconvertire il dizionario degli oggetti nel DTO digitato, ad esempio:
var result = objDictionary.FromObjectDictionary(theResultType);