No sólo de unmarshal vive el TJSONUNMarshal | Puro Delphi

Cursos, artículos, noticias y herramientas Delphi VCL (Visual Component Library) / FMX (Firemonkey)

No sólo de unmarshal vive el TJSONUNMarshal

Logo JSONObjectEs normal que en nuestro servidor DataSnap tengamos un método cuyo parámetro de entrada sea un objeto. En cuanto al protocolo HTTP hoy en día la RTL se encarga de hacer por nosotros la conversión del JSON enviado desde el cliente a una clase nativa de Delphi, sin la necesidad de nuestra intervención… él mismo utiliza el TJSONMarshal y el TJSONUNMarshal para lograrlo –Hace el trabajo sucio por nosotros–, es decir… hoy en día es aceptable tener declarado dicho método como algo así:

En lugar del típico:

Como puedes notar en el primer caso el tipo de parámetro es directamente una clase creada por nosotros mismos, incluso el resultado también –aunque lo que realmente “viaja” es un JSONValue–. Mientras que en el segundo caso ambos son un TJSONObject.

Y no con esto estoy diciendo que la manera típica de trabajarlo esté mal ni mucho menos, de hecho ofrece una manera de controlar nosotros mismos la situación en caso que el objeto enviado tenga la estructura incorrecta.

En este artículo pretendo abarcar el tema… “No sólo de unmarshal vive el TJSONUNMarshal”, para tratar en los 2 casos una exception común cuando se trabaja de esta manera, parecida a la siguiente:

—————————
Debugger Exception Notification
—————————
Project Project1.exe raised exception class EConversionError with message ‘Internal: Cannot instantiate type NameSpace.TClaseDescendiente’.
—————————
Break Continue Help
—————————

 

Supongamos como en los párrafos anteriores, que tenemos un método que recibe un objeto como parámetro, pero ahora añadimos un nivel típico de dificultad y es que resulta que la idea no es que sólo se puedan recibir parámetros con ese tipo exacto, sino también poder recibir a sus descendientes, como en cualquier método de Delphi.

Es bien sabido que podemos hacer lo siguiente con cualquier método “usual” en Delphi:

Y llamarlo de cualquiera de las 2 siguientes maneras, suponiendo que TNevera viene de TElectrodomestico:

Funcionaría naturalmente si el método no es remoto. Pero si lo fuera y desde un cliente enviamos el objeto, ya sea desde PHP, JAVA o cualquier lenguaje, incluido Delphi… quizá utilizando el método contemplado en este mismo blog anteriormente. Seguramente sólo tendría el funcionamiento esperado si se envía la variable vElectrodomestico, pero al enviar a vNevera tendríamos problemas y más en el caso que el servidor no estuviera instanciando ninguna variable del tipo TNevera, elevando la exception (EConversionError) mencionada al inicio de este artículo.

Esto es debido a que el TJSONUNMarshal no encuentra la clase TNevera. De hecho si usamos el segundo caso expuesto en principio y depuramos, notaremos que justo en el método unmarshal se eleva dicha exception:

Y para el primer caso, ni siquiera entraría al método ya que el Unmarshal lo ejecutaría la RTL antes de llamar a nuestro método.

¿Cómo solucionamos este asunto?, bueno, la solución que he encontrado es bastante simple, sólo es cuestión de registrar la clase en la unidad donde esté declarada, tal y cual como si de un paquete se tratara. Ejemplo, tenemos la unidad donde está la clase TNevera, con algo así:

Vamos al final de la unidad y creamos –si no existe– la sección initialization, para luego registrar dicha clase:

Y eso es todo, finalmente podremos enviar la clase base y todos sus descendientes registrados sin esa odiosa exception de por medio.

Espero les sea útil este artículo, seguramente tendrás algo que aportar a él o quizá tendrás algún comentario, así que te invito a expresarlo. Bye.

P.D: He decidido publicar primero este artículo en base a la encuesta realizada en la cuenta de Twitter de PuroDelphi.


Escriba un comentario

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *

  • RSS

  • Categorías

  • Nube de etiquetas

  • Usuario