カスタムデータ構造があり、これをJava Beanに変換する必要があります。 そのデータ構造には通常、すべてがStringとして格納されますが、Beanは型付き属性を持ちます。カスタムデータ構造体をSpringを使用してBeanに変換する
属性の名前は、データ構造とBeanの両方で同じです。
実行時にBeanの実際のターゲットタイプが決定され、カスタムフォーマットされた日付文字列からJoda DateTimeオブジェクトに変換する必要があります。
可能なタイプごとにメソッドを記述するのに手間がかかりませんが、これにはどのような解決策がありますか?
私のコードは、Springコンテナで実行されているので、私は現在、私は標準の変換(文字列 - >のBigDecimalなど)を気にする必要はいけないスプリングスBeanWrapperためつもりだし、それを構成し:
- ConversionService +カスタムコンバーター
- カスタムPropertyEditorはしかし
は、BeanWrapperImplは、それが基本的に内部クラスであることを言って、ノートを持っているので、私はそれを使用すべきかに関して、または場合は少し混乱していますが代替案。ここで
は、コードは次のとおりです。
import org.joda.time.DateTime;
import org.junit.Test;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.support.DefaultConversionService;
import java.beans.PropertyEditorSupport;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
public class BeanWrapperTest
{
private static InputDataStructure createInputDataStructure()
{
return new InputDataStructure(Arrays.asList(
map(mapEntry("name", "some name"),
mapEntry("bigDecimal", "12.34")),
map(mapEntry("dateTime", "2017-03-02T09:30:00.0Z"))
));
}
private Map<String, String> toMap(InputDataStructure inputDataStructure)
{
return inputDataStructure.data.stream()
.flatMap(innerMap -> innerMap.entrySet().stream())
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue
));
}
@Test
public void copy_alternative_using_conversion_service()
{
// set up a conversion service and add the special date converter
// and configure BeanWrapper with that conversion service
DefaultConversionService defaultConversionService = new DefaultConversionService();
defaultConversionService.addConverter(new CustomDateConverter());
BeanWrapper beanWrapper = new BeanWrapperImpl(DestinationClass.class);
beanWrapper.setConversionService(defaultConversionService);
// copy all values into a Map
// and loop over that map and use BeanWrapper to copy the properties
Map<String, String> values = toMap(createInputDataStructure());
values.forEach(beanWrapper::setPropertyValue);
// bam!
System.out.println(beanWrapper.getWrappedInstance());
}
@Test
public void copy_alternative_using_formatters()
{
// configure BeanWrapper with a custom property editor
BeanWrapper beanWrapper = new BeanWrapperImpl(DestinationClass.class);
beanWrapper.registerCustomEditor(DateTime.class, new CustomDateEditor());
// copy all values into a Map
// and loop over that map and use BeanWrapper to copy the properties
Map<String, String> values = toMap(createInputDataStructure());
values.forEach(beanWrapper::setPropertyValue);
// bam!
System.out.println(beanWrapper.getWrappedInstance());
}
@SafeVarargs
private static <K, V> Map<K, V> map(Map.Entry<K, V>... entries)
{
Map<K, V> map = new HashMap<>();
for (Map.Entry<K, V> e : entries) {
map.put(e.getKey(), e.getValue());
}
return map;
}
private static <K, V> Map.Entry<K, V> mapEntry(K key, V value)
{
return new AbstractMap.SimpleImmutableEntry<>(key, value);
}
private static class InputDataStructure
{
private final List<Map<String, String>> data;
InputDataStructure(List<Map<String, String>> data)
{
this.data = data;
}
}
private static class DestinationClass
{
private String name;
private BigDecimal bigDecimal;
private DateTime dateTime;
public String getName()
{
return name;
}
public DestinationClass setName(String name)
{
this.name = name;
return this;
}
public BigDecimal getBigDecimal()
{
return bigDecimal;
}
public DestinationClass setBigDecimal(BigDecimal bigDecimal)
{
this.bigDecimal = bigDecimal;
return this;
}
public DateTime getDateTime()
{
return dateTime;
}
public DestinationClass setDateTime(DateTime dateTime)
{
this.dateTime = dateTime;
return this;
}
@Override public String toString()
{
return "DestinationClass{" + "name='" + name + '\'' +
", bigDecimal=" + bigDecimal +
", dateTime=" + dateTime +
'}';
}
}
private static class CustomDateConverter implements Converter<String, DateTime>
{
@Override public DateTime convert(String source)
{
// try whatever date format would be expected
return DateTime.parse(source);
}
}
private class CustomDateEditor extends PropertyEditorSupport
{
@Override
public void setAsText(String text)
{
// try whatever date format would be expected
setValue(DateTime.parse(text));
}
}
}