2011-10-04 16 views
5

He estado usando AutoBeans para mapear datos JSON procedentes de un servicio web no GWT-RPC basado en Java. Todo ha estado funcionando hasta ahora excepto por un mapeo.¿Hay alguna manera de abatir un AutoBean de GWT?

En el lado del servidor, la clase tiene una propiedad de tipo Mapa donde MyAbstractParentObject es la clase principal de aproximadamente 15 clases secundarias diferentes.

Cuando lo correlaciono con una interfaz AutoBean correspondiente en el cliente, no puedo bajar MyAbstractParentObject a su tipo secundario después de que se haya descodificado. Busqué en todos los documentos de GWT y en "Google" para ver si AutoBeans incluso tiene soporte polimórfico pero no pudo obtener una respuesta de ninguna manera. Los interceptores y las categorías no parecen ser capaces de manejar esto, solo los métodos que desean que existan en la interfaz no son getters/setters.

Estaba intentando hacer una solución utilizando el campo tipo en los datos JSON para crear una instancia de la clase secundaria pero el AutoBean no me da acceso al JSON sin formato, aunque en el depurador puedo verlo como un campo protegido llamado 'datos'. Si intento decodificar el bean original, solo tendrá los campos en MyAbstractParentObject.

Las únicas alternativas que puedo ver son:

  1. Extender o crear mi propia AutoBeanCodex que puede manejar adecuadamente los hijos de MyAbstractParentObject cuando se decodifica la JSON.
  2. Busque una forma de obtener el JSON sin procesar en el AutoBean MyAbstractParentObject y utilícelo para crear una instancia de la clase hija sobre la marcha.
  3. Cambie a algún otro marco de serialización JSON-GWT como GWTProJSONSerializer o piriti.

Cualquier ayuda sería apreciada.

Respuesta

4

sé que esto se le preguntó hace mucho tiempo, pero me costó encontrar una respuesta también. Me di cuenta de que los AutoBeans, ya que básicamente son envoltorios sofisticados para el JSON, todavía contienen todos los datos de los campos del objeto secundario al que desea aplicarlos. Así que escribí un método como este:

public <A, B> B cast(A sourceObject, Class<B> targetClass) 
{ 
    AutoBean<A> sourceBean = AutoBeanUtils.getAutoBean(sourceObject); // Get the corresponding AutoBean. 
    HasSplittable splittableBean = (HasSplittable) sourceBean;  // Implementation (if still AbstractAutoBean) supports this interface ;) 
    Splittable splittable = splittableBean.getSplittable().deepCopy(); // If you don't copy it, decode() tries to be clever and returns 
                     // the original bean! 
    AutoBean<B> targetBean = AutoBeanCodex.decode(typeFactory, targetClass, splittable); // Create new AutoBean of 
                          // the target type. 
    return targetBean.as(); // Get the proxy for the outside world. 
} 

--donde typeFactory extiende AutoBeanFactory, como se puede ver.

Ha funcionado lo suficientemente bien para mí. El bit más complicado fue el lanzamiento a HasSplittable, ya que AutoBean no extiende esa interfaz, pero AbstractAutoBean (que implementa AutoBean) lo hace, y una subclase de eso es lo que devuelve las llamadas a getAutoBean().

También debe copiar el Splittable, de lo contrario, AutoBeanCodex piensa: "¡hey, ya tengo un AutoBean para ese Splittable! ¡Aquí tienes!" - y solo te da el original. ;)

De todos modos, puede lanzar hacia abajo, hacia arriba ... hacia los lados!: P

Última edición: Tropezando con esto meses después, pensé que agregaría una pequeña advertencia sobre algo que Jonathan mencionó a continuación. El método que he descrito aquí está diseñado para ser utilizado en un AutoBean que no ha sido modificado desde que se deserializó. Eso es porque (AFAIK) no hay garantía de que los instaladores a los que llame actualicen realmente el JSON (necesario para el casting). Probablemente esto no sea un gran problema, ya que normalmente usará esto cuando tenga un DTO entrante y desee convertirlo al real tipo ASAP, antes de hacer cualquier otra cosa con él. En nuestro caso, ninguno de nuestros AutoBeans tenía instaladores, por lo que no fue realmente un problema. ;)

Después de que lo hayas lanzado, puedes hacer lo que quieras con el grano resultante, ¡que recién salió de la fábrica después de todo!

+0

He tenido que hacer cosas similares con AutoBeans, pero hago una codificación completa para obtener el Splittable de un AutoBean Splittable split = AutoBeanCodex.encode (AutoBeanUtils.getAutoBean (sourceBean)); – Jonathan

+0

@Jonathan Probé 'AutoBeanCodex.encode()'; funciona para upcasting, pero no para downcasting - una pena, ya que sería una manera fácil de hacerlo. :) 'encode()' utiliza el patrón de visitante para recorrer las propiedades del bean y generar el nuevo 'Splittable'. Lamentablemente, el JSON de origen tiene propiedades que no son accesibles a través de ese bean, pero que son necesarias para 'downcast' ... y el visitante no las ve, por lo que el JSON de 'encode()' 's' Splittable 'no los tiene. :( ... De ahí extrañamente obteniendo el 'Splittable' directamente y copiándolo; se decodifica correctamente ya que toda la información está todavía allí. –

+0

Veo a qué te refieres. Ahora me parece que ambas técnicas tienen su casos de uso. He estado utilizando el método que mencioné anteriormente porque la mayoría de las veces cuando estoy transformando un autobean en otro, he hecho cambios antes de hacerlo. Por lo tanto, en ese caso, necesito el recorrido completo del visitante para poder para obtener toda la información corregida correcta. Pendiente resbaladiza aquí ya que el uso de 'HasSplittable' puede ser excelente si no has realizado cambios, y sabes ** que no se han realizado cambios. De lo contrario, eres la única opción. para realizar la codificación completa. A menos que me falta algo ..... – Jonathan

Cuestiones relacionadas