2012-01-17 13 views
18

¿Hay una biblioteca que puede hacer lo siguiente ?:establecer los campos objeto de HashMap

Dado un objeto y un HashMap, enumera las llaves del Hashmap y mira hacia arriba los emisores de estas teclas en el objeto y conjuntos los valores asociados. Algo parecido a lo siguiente:

public Object setData(Object object, HashMap<String, Object> fields) { 
    for (Entry<String, Object> entry : fields.entrySet()) { 
     Method m = object.getClass().getMethod("set" + entry.getKey(), entry.getValue().getClass()); 
     if (m != null) { 
     m.invoke(object, entry.getValue()); 
     } 
    } 
    return object; 
} 

La tarea parece simple en la primera mirada, pero hay algunos matices que espero que alguien ya ha atendido. Como saben, reinventar la rueda (la buena rueda) es un mal enfoque.

Respuesta

17

Look at Apache Commons BeanUtils

org.apache.commons.beanutils.BeanUtils.populate(Object bean, Map properties) 

Javadoc:
pueblan las propiedades JavaBeans del grano especificado, basado en los pares de nombre/valor especificado. Este método utiliza las API de reflexión de Java para identificar los nombres de los métodos "establecedores de propiedades" correspondientes, y trata con los argumentos del setter de tipo String, boolean, int, long, float y double.

+2

La advertencia "solo trata con argumentos setter de tipo String, boolean, int, long, flat y double" es MUY digna de mención, por eso creo que la respuesta a continuación (pero utilizando BeanUtils.copyProperty() en lugar de BeanUtils.setProperty()) es la mejor alternativa. – fragorl

6

Mejor uso de clase BeanUtils:

public Object setData(Object object, HashMap<String, Object> fields) { 
    for(Entry<String, Object> entry : fields.entrySet()) { 
     BeanUtils.setProperty(object, entry.getKey(), entry.getValue()); 
    } 
    return object; 
} 
+0

Gracias @Wojtek O., ¡con su pista encontré el método populate justo antes de que e-zinc respondiera con él! – forker

3

tengo una clase BeanAsMap que escribí hace mucho tiempo. El método asMap devuelve Map que es una vista en un bean Java (POJO). Puede llamar al putAll en ese Map, pasándole el Map del que desea copiar los datos.

Siéntase libre de utilizar mi código mencionado anteriormente.

Ejemplo:

MyClass bean = ...; 
Map<String, Object> inputData = ...; 

Map<String, Object> view = BeanAsMap.asMap(bean); 
view.putAll(inputData); 
+0

Su código está bien @Jesper, pero la pregunta es 'Mapa -> Bean' y ** NO **' Bean -> Mapa' –

+1

@FelipeConde Mi código funciona de dos maneras: puede crear una nueva instancia de una clase de bean, luego, envuélvalo con 'BeanAsMap' y llame a' put' en el mapa que establecerá las propiedades de los beans.Si tiene un mapa existente, puede llamar a 'putAll' en el mapa del contenedor para copiar los valores del mapa existente en el bean. – Jesper

2

BeanUtils está muy bien.

Pero, como buena práctica, no escribiría código que use la reflexión. O como la última solución que tengo, si no se ha encontrado ninguna otra.

Este código no se puede rastrear en IDE como Eclipse (sin jerarquía de llamadas), lo que hace que el desarrollador piense que nunca se llama a los instaladores. Él puede romper tu código y eso aún se compilará.

Un nivel demasiado alto de abstracción como este hace que el código sea difícil de entender.

El código que se ofusca se romperá por el ofuscador en sí al escribir tales cosas.

La mejor solución sería reconsiderar el uso de la reflexión para establecer los campos del objeto.

+0

No podría estar más de acuerdo. –

+1

Aunque estoy de acuerdo en que la reflexión no se debe utilizar como una herramienta de propósito general, ocasionalmente hay buenas razones para usarla (por ejemplo, establecer las propiedades de un objeto Bean de JSON u otra fuente dinámica). –

Cuestiones relacionadas