使用SuperCSV ICsvBeanReader解析枚举

Tom*_*ski 5 java csv enums supercsv

我解析CSV文件并使用supercsv创建域对象.我的域对象有一个枚举字段,例如:

public class TypeWithEnum {

private Type type;

public TypeWithEnum(Type type) {
    this.type = type;
}

public Type getType() {
    return type;
}

public void setType(Type type) {
    this.type = type;
}
}
Run Code Online (Sandbox Code Playgroud)

我的枚举看起来像这样:

public enum Type {

    CANCEL, REFUND
}
Run Code Online (Sandbox Code Playgroud)

尝试使用此CSV文件创建bean:

final String[] header = new String[]{ "type"  };
ICsvBeanReader inFile = new CsvBeanReader(new FileReader(
    getFilePath(this.getClass(), "learning/enums.csv")), CsvPreference.STANDARD_PREFERENCE);

final CellProcessor[] processors = 
    new CellProcessor[]{ TODO WHAT TO PUT HERE? };
TypeWithEnum myEnum = inFile.read(
    TypeWithEnum.class, header, processors);
Run Code Online (Sandbox Code Playgroud)

在填充对象上下文时失败并显示错误:null offending processor:null org.supercsv.io.CsvBeanReader.fillObject(Unknown Source)at org.supercsv.io.CsvBeanReader.read(Unknown Source)

解析枚举的任何提示?我应该为此编写自己的处理器吗?

我已经尝试编写自己的处理器,如下所示:

class MyCellProcessor extends CellProcessorAdaptor {
    public Object execute(Object value, CSVContext context) {
        Type type = Type.valueOf(value.toString());
        return next.execute(type, context);
    }
}
Run Code Online (Sandbox Code Playgroud)

但它死于同样的例外.

我的enums.csv文件的内容很简单:

取消
退款

Jam*_*ett 7

您获得的异常是因为CsvBeanReader无法实例化您的TypeWithEnum类,因为它没有默认(无参数)构造函数.打印堆栈跟踪可能是一个好主意,这样您就可以看到出错的全部细节.

超级CSV依赖于这样一个事实:您应该提供一个有效的Java bean,即一个具有默认构造函数的类和每个字段的公共getter/setter.

因此,您可以通过添加以下内容来修复异常TypeWithEnum:

public TypeWithEnum(){
}
Run Code Online (Sandbox Code Playgroud)

至于解析枚举的提示,两个最简单的选项是:

1.使用HashMapper处理器

@Test
public void hashMapperTest() throws Exception {

    // two lines of input
    String input = "CANCEL\nREFUND";

    // you could also put the header in the CSV file
    // and use inFile.getCSVHeader(true)
    final String[] header = new String[] { "type" };

    // map from enum name to enum
    final Map<Object, Object> typeMap = new HashMap<Object, Object>();
    for( Type t : Type.values() ) {
        typeMap.put(t.name(), t);
    }

    // HashMapper will convert from the enum name to the enum
    final CellProcessor[] processors = 
        new CellProcessor[] { new HashMapper(typeMap) };

    ICsvBeanReader inFile = 
        new CsvBeanReader(new StringReader(input),
        CsvPreference.STANDARD_PREFERENCE);

    TypeWithEnum myEnum;
    while((myEnum = inFile.read(TypeWithEnum.class, header, processors)) !=null){
        System.out.println(myEnum.getType());
    }

}
Run Code Online (Sandbox Code Playgroud)

2.创建自定义CellProcessor

创建您的处理器

package org.supercsv;

import org.supercsv.cellprocessor.CellProcessorAdaptor;
import org.supercsv.cellprocessor.ift.CellProcessor;
import org.supercsv.exception.SuperCSVException;
import org.supercsv.util.CSVContext;

public class TypeProcessor extends CellProcessorAdaptor {

    public TypeProcessor() {
        super();
    }

    public TypeProcessor(CellProcessor next) {
        super(next);
    }

    public Object execute(Object value, CSVContext context) {

        if (!(value instanceof String)){
            throw new SuperCSVException("input should be a String!");
        }

        // parse the String to a Type
        Type type = Type.valueOf((String) value);

        // execute the next processor in the chain
        return next.execute(type, context);
    }

}
Run Code Online (Sandbox Code Playgroud)

用它!

@Test
public void customProcessorTest() throws Exception {

    // two lines of input
    String input = "CANCEL\nREFUND";

    final String[] header = new String[] { "type" };

    // HashMapper will convert from the enum name to the enum
    final CellProcessor[] processors = 
        new CellProcessor[] { new TypeProcessor() };

    ICsvBeanReader inFile = 
        new CsvBeanReader(new StringReader(input),
        CsvPreference.STANDARD_PREFERENCE);
    TypeWithEnum myEnum;
    while((myEnum = inFile.read(TypeWithEnum.class, header, processors)) !=null){
        System.out.println(myEnum.getType());
    }

}
Run Code Online (Sandbox Code Playgroud)

我正在研究即将发布的Super CSV版本.我将确保更新网站,以明确您必须拥有一个有效的Java bean - 可能是对可用处理器的描述,对于那些不想阅读Javadoc的人.


oer*_*ers 1

我尝试重现您的错误,但一切都对我有用。我使用 SuperCSV 1.52:

  private enum ENUMS_VALUES{TEST1, TEST2, TEST3};
  @Test
  public void testEnum3() throws IOException
  {
    String testInput = new String("TEST1\nTEST2\nTEST3");
    ICsvBeanReader  reader = new CsvBeanReader(new StringReader(testInput), CsvPreference.EXCEL_NORTH_EUROPE_PREFERENCE);
    final String[] header = new String[] {"header"};
    reader.read(this.getClass(), header, new CellProcessor[] {new CellProcessorAdaptor() {

      @Override
      public Object execute(Object pValue, CSVContext pContext)
      {
        return next.execute(ENUMS_VALUES.valueOf((String)pValue), pContext);
      }}});

  }

  @Test
  public void testEnum4() throws IOException
  {
    String testInput = new String("TEST1\nTEST2\nTEST3");
    ICsvBeanReader reader = new CsvBeanReader(new StringReader(testInput), CsvPreference.EXCEL_NORTH_EUROPE_PREFERENCE);
    final String[] header = new String[] {"header"};
    reader.read(this.getClass(), header, new CellProcessor[] {new CellProcessorAdaptor()
    {

      @Override
      public Object execute(Object pValue, CSVContext pContext)
      {
        return ENUMS_VALUES.valueOf((String)pValue);
      }}});
  }

  public void setHeader(ENUMS_VALUES value)
  {
    System.out.println(value);
  }
Run Code Online (Sandbox Code Playgroud)