2017-03-02 105 views
0

我們有一個需要轉換爲java bean的自定義數據結構。 該數據結構通常將所有內容都包含爲字符串,但該bean將具有輸入的屬性。使用Spring將自定義數據結構轉換爲bean

這些屬性在數據結構和bean中都被命名爲相同。

該bean的實際目標類型是在運行時確定的,爲了將它調好一點,我們還需要從自定義格式化的日期字符串轉換爲Joda DateTime對象。

因此,爲每種可能的類型編寫一個方法都很簡單,對此有什麼好的解決方案?

  • : -

    因爲我的代碼是在Spring容器中運行,目前我正在去爲泉的BeanWrapper所以我沒有去關心標準轉換(字符串>的BigDecimal等),並配置它ConversionService +自定義轉換器

  • 自定義屬性編輯

然而,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

還有就是要解決你的問題一個取巧的方法。你可以將你的對象轉換成json字符串,然後使用com.fasterxml.jackson.databind.ObjectMapper將json字符串寫入目標對象