2017-03-02 3 views
0

カスタムデータ構造があり、これを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)); 
     } 
    } 
} 

答えて

0

あなたの問題を解決するためにトリッキーな方法があります。 com.fasterxml.jackson.databind.ObjectMapperを使用してオブジェクトをjson文字列に変換し、ターゲットオブジェクトにjson文字列を書き込むことができます

関連する問題