2017-03-02 77 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字符串写入目标对象