2012-01-17 10 views
18

Czy istnieje biblioteki, które można wykonać następujące czynności ?:Zestaw pól obiektu z HashMap

Biorąc pod uwagę przedmiot i HashMap, to wylicza klucze HashMap i patrzy w górę ustawiające dla tych kluczy w obiekcie i zestawy powiązane wartości. Coś się tak:

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; 
} 

Zadanie wygląda prosta na pierwszy rzut oka, ale są pewne niuanse, które mam nadzieję, że ktoś już załatwione. Jak wiecie, wymyślanie koła (dobre koło) to złe podejście.

Odpowiedz

17

Spójrz Apache Gmin BeanUtils

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

Javadoc:
Wypełnianie JavaBeans właściwości określonego fasola, na podstawie określonych par nazwa/wartość. Ta metoda korzysta z interfejsów Java API do rozpoznawania odpowiednich nazw metod "ustawiania właściwości" i zajmuje się argumentami ustawiającymi typu String, boolean, int, long, float i double.

+2

The caveat "dotyczy tylko argumentów ustawiających typu String, boolean, int, long, flat i double" jest BARDZO wart uwagi, z tego powodu uważam, że poniżej odpowiedź (ale przy użyciu BeanUtils.copyProperty() zamiast BeanUtils.setProperty()) jest lepszą alternatywą. – fragorl

6

Lepsze wykorzystanie BeanUtils klasa:

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

Dzięki @Wojtek O. Z twoją podpowiedzią znalazłem metodę zaludniania tuż przed odpowiedzią e-cynku! – forker

3

Mam BeanAsMap klasę, że napisałem dawno temu. Metoda ta zwraca wartość asMap, która jest widokiem na komponent bean Java (POJO). Możesz zadzwonić pod numer putAll na ten numer Map, przekazując mu numer Map, z którego chcesz skopiować dane.

Zapraszam do korzystania z mojego kodu wspomnianego powyżej.

przykład:

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

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

Twój kod jest w porządku @Jesper, ale pytanie brzmi "Mapa -> Fasola" i ** NIE ** "Fasola -> Mapa" –

+1

@FelipeConde Mój kod działa na dwa sposoby - możesz utworzyć nowe wystąpienie klasy ziarnistej, następnie zawiń go 'BeanAsMap' i wywołaj' put' na mapie, która ustawi właściwości fasoli.Jeśli masz już mapę, możesz wywołać 'putAll' na mapie opakowania, aby skopiować istniejące wartości mapy do komponentu bean. – Jesper

2

BeanUtils jest w porządku.

Ale, jako dobra praktyka, nie pisałbym kodu, który używa odbicia. Lub jako ostatnie rozwiązanie, jeśli nie znaleziono żadnego innego.

Ten kod nie może być śledzony w środowisku IDE, podobnie jak Eclipse (bez hierarchii połączeń), przez co programista uważa, że ​​setery nie są nigdy wywoływane. Potrafi złamać twój kod i to się jeszcze skompiluje.

Zbyt wysoki poziom abstrakcji sprawia, że ​​kod jest trudny do zrozumienia.

Kod, który jest zaciemniany, zostanie uszkodzony przez samego obfuscatora podczas pisania takich rzeczy.

Najlepszym rozwiązaniem byłoby ponowne przemyślenie użycia odbicia w celu ustawienia pól obiektu.

+0

Nie można się zgodzić na więcej. –

+1

Chociaż zgadzam się, że refleksja nie powinna być używana jako narzędzie ogólnego przeznaczenia, istnieją czasami dobre powody, aby z niej korzystać (na przykład, ustawiając właściwości obiektu Bean z JSON lub innego dynamicznego źródła). –