我有以下课程..
SurveyResponse.java
import java.util.List;
public class SurveyResponse {
private int age;
private Boolean consentGiven;
private List<Answer> answers;
public SurveyResponse() {
}
public SurveyResponse(final int age, final Boolean consentGiven, final List<Answer>
answers) {
this.age = age;
this.consentGiven = consentGiven;
this.answers = answers;
}
public int getAge() {
return age;
}
public List<Answer> getAnswers() {
return answers;
}
public Boolean getConsentGiven() {
return consentGiven;
}
public void setAge(final int age) {
this.age = age;
}
public void setAnswers(final List<Answer> answers) {
this.answers = answers;
}
public void setConsentGiven(final Boolean consentGiven) {
this.consentGiven = consentGiven;
}
@Override
public String toString() {
return String.format("SurveyResponse [age=%s, consentGiven=%s, answers=%s]", age,
consentGiven, answers);
}
}
Answer.java
public class Answer {
private Integer questionNo;
private String answer;
public Answer() {
}
public Answer(final Integer questionNo, final String answer) {
this.questionNo = questionNo;
this.answer = answer;
}
public String getAnswer() {
return answer;
}
public Integer getQuestionNo() {
return questionNo;
}
public void setAnswer(final String answer) {
this.answer = answer;
}
public void setQuestionNo(final Integer questionNo) {
this.questionNo = questionNo;
}
@Override
public String toString() {
return String.format("Answer [questionNo=%s, answer=%s]", questionNo, answer);
}
}
和我的 Main 类循环可以正常工作 -
import java.io.FileWriter;
import java.util.Arrays;
import java.util.List;
import org.supercsv.cellprocessor.FmtBool;
import org.supercsv.cellprocessor.Optional;
import org.supercsv.cellprocessor.Token;
import org.supercsv.cellprocessor.constraint.NotNull;
import org.supercsv.cellprocessor.ift.CellProcessor;
import org.supercsv.io.dozer.CsvDozerBeanWriter;
import org.supercsv.io.dozer.ICsvDozerBeanWriter;
import org.supercsv.prefs.CsvPreference;
public class Main {
private static final String[] FIELD_MAPPING = new String[] { "age", // simple field
mapping
// (like
CsvBeanReader)
"consentGiven", // as above
"answers[0].questionNo", // indexed (first element) + deep mapping
"answers[0].answer", "answers[1].questionNo", // indexed (second element) + deep
mapping
"answers[1].answer", "answers[2].questionNo", "answers[2].answer" };
/**
* @param args
* @throws Exception
*/
public static void main(final String[] args) throws Exception {
writeWithDozerCsvBeanWriter();
}
private static void writeWithDozerCsvBeanWriter() throws Exception {
final CellProcessor[] processors = new CellProcessor[] { new Token(0, null), // age
new FmtBool("Y", "N"), // consent
new NotNull(), // questionNo 1
new Optional(), // answer 1
new NotNull(), // questionNo 2
new Optional(), // answer 2
new NotNull(), // questionNo 3
new Optional() }; // answer 4
// create the survey responses to write
final SurveyResponse response1 =
new SurveyResponse(18, true, Arrays.asList(new Answer(1, "Twelve"), new
Answer(2,
"Albert Einstein"), new Answer(3, "Big Bang Theory")));
final SurveyResponse response2 =
new SurveyResponse(0, true, Arrays.asList(new Answer(1, "Thirteen"), new
Answer(2,
"Nikola Tesla"), new Answer(3, "Stargate")));
final SurveyResponse response3 =
new SurveyResponse(42, false, Arrays.asList(new Answer(1, null), new Answer(2,
"Carl Sagan"), new Answer(3, "Star Wars")));
final List<SurveyResponse> surveyResponses =
Arrays.asList(response1, response2, response3);
ICsvDozerBeanWriter beanWriter = null;
try {
beanWriter =
new CsvDozerBeanWriter(new
FileWriter("C:\\Users\\Desktop\\Test.csv"),
CsvPreference.STANDARD_PREFERENCE);
// configure the mapping from the fields to the CSV columns
beanWriter.configureBeanMapping(SurveyResponse.class, FIELD_MAPPING);
// write the header
beanWriter.writeHeader("age", "consentGiven", "questionNo1", "answer1",
"questionNo2", "answer2", "questionNo3", "answer3");
// write the beans
for (final SurveyResponse surveyResponse : surveyResponses) {
beanWriter.write(surveyResponse, processors);
}
} finally {
if (beanWriter != null) {
beanWriter.close();
}
}
}
}
我想避免在字段映射和处理器数组中进行循环,因为在我们的应用中,我们有大约100到1000个答案。所以我写了下面哪个不行。有人可以解释为什么以下不起作用?
Main2.java
import java.io.FileWriter;
import java.util.Arrays;
import java.util.List;
import org.supercsv.cellprocessor.FmtBool;
import org.supercsv.cellprocessor.Optional;
import org.supercsv.cellprocessor.Token;
import org.supercsv.cellprocessor.constraint.NotNull;
import org.supercsv.cellprocessor.ift.CellProcessor;
import org.supercsv.io.dozer.CsvDozerBeanWriter;
import org.supercsv.io.dozer.ICsvDozerBeanWriter;
import org.supercsv.prefs.CsvPreference;
public class Main2 {
private static final String[] FIELD_MAPPING = new String[] { "age", "consentGiven",
"answers.questionNo", "answers.answer" };
/**
* @param args
* @throws Exception
*/
public static void main(final String[] args) throws Exception {
writeWithDozerCsvBeanWriter();
}
private static void writeWithDozerCsvBeanWriter() throws Exception {
final CellProcessor[] processors = new CellProcessor[] { new Token(0, null), // age
new FmtBool("Y", "N"), // consent
new NotNull(), // questionNo
new Optional() // answer
};
// create the survey responses to write
final SurveyResponse response1 =
new SurveyResponse(18, true, Arrays.asList(new Answer(1, "Twelve"), new
Answer(2,
"Albert Einstein"), new Answer(3, "Big Bang Theory")));
final SurveyResponse response2 =
new SurveyResponse(0, true, Arrays.asList(new Answer(1, "Thirteen"), new
Answer(2,
"Nikola Tesla"), new Answer(3, "Stargate")));
final SurveyResponse response3 =
new SurveyResponse(42, false, Arrays.asList(new Answer(1, null), new Answer(2,
"Carl Sagan"), new Answer(3, "Star Wars")));
final List<SurveyResponse> surveyResponses =
Arrays.asList(response1, response2, response3);
ICsvDozerBeanWriter beanWriter = null;
try {
beanWriter =
new CsvDozerBeanWriter(new
FileWriter("C:\\Users\\Desktop\\Test.csv"),
CsvPreference.STANDARD_PREFERENCE);
// configure the mapping from the fields to the CSV columns
beanWriter.configureBeanMapping(SurveyResponse.class, FIELD_MAPPING);
// write the header
beanWriter.writeHeader("age", "consentGiven", "questionNo1", "answer1");
// write the beans
for (final SurveyResponse surveyResponse : surveyResponses) {
beanWriter.write(surveyResponse, processors);
}
} finally {
if (beanWriter != null) {
beanWriter.close();
}
}
}
}
这是错误
6 [main] INFO org.dozer.config.GlobalSettings - Trying to find Dozer configuration
file: dozer.properties
14 [main] WARN org.dozer.config.GlobalSettings - Dozer configuration file not found:
dozer.properties. Using defaults for all Dozer global properties.
15 [main] INFO org.dozer.DozerInitializer - Initializing Dozer. Version: 5.4.0, Thread
Name: main
64 [main] INFO org.dozer.jmx.JMXPlatformImpl - Dozer JMX MBean
[org.dozer.jmx:type=DozerStatisticsController] auto registered with the Platform MBean
Server
65 [main] INFO org.dozer.jmx.JMXPlatformImpl - Dozer JMX MBean
[org.dozer.jmx:type=DozerAdminController] auto registered with the Platform MBean
Server
68 [main] INFO org.dozer.DozerBeanMapper - Initializing a new instance of dozer bean
mapper.
156 [main] ERROR org.dozer.MappingProcessor - Field mapping error -->
MapId: null
Type: null
Source parent class: SurveyResponse
Source field name: answers.questionNo
Source field type: null
Source field value: null
Dest parent class: org.supercsv.io.dozer.CsvDozerBeanData
Dest field name: columns
Dest field type: java.util.List
java.lang.IllegalArgumentException: object is not an instance of declaring class
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.dozer.util.ReflectionUtils.invoke(ReflectionUtils.java:323)
at
org.dozer.propertydescriptor.GetterSetterPropertyDescriptor.
getDeepSrcFieldValue(GetterSetterPropertyDescriptor.java:122)
at org.dozer.propertydescriptor.GetterSetterPropertyDescriptor.
getPropertyValue(GetterSetterPropertyDescriptor.java:75)
at org.dozer.fieldmap.FieldMap.getSrcFieldValue(FieldMap.java:84)
at org.dozer.MappingProcessor.mapField(MappingProcessor.java:275)
at org.dozer.MappingProcessor.map(MappingProcessor.java:248)
at org.dozer.MappingProcessor.map(MappingProcessor.java:197)
at org.dozer.MappingProcessor.map(MappingProcessor.java:187)
at org.dozer.MappingProcessor.map(MappingProcessor.java:133)
at org.dozer.MappingProcessor.map(MappingProcessor.java:128)
at org.dozer.DozerBeanMapper.map(DozerBeanMapper.java:127)
at org.supercsv.io.dozer.CsvDozerBeanWriter.write(CsvDozerBeanWriter.java:132)
at MainAvoidIndexing.writeWithDozerCsvBeanWriter(MainAvoidIndexing.java:68)
at MainAvoidIndexing.main(MainAvoidIndexing.java:29)
Exception in thread "main" java.lang.IllegalArgumentException: object is not an
instance of declaring class
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at
sun.reflect.DelegatingMethodAccessorImpl.
invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.dozer.util.ReflectionUtils.invoke(ReflectionUtils.java:323)
at org.dozer.propertydescriptor.GetterSetterPropertyDescriptor.
getDeepSrcFieldValue(GetterSetterPropertyDescriptor.java:122)
at
org.dozer.propertydescriptor.GetterSetterPropertyDescriptor.
getPropertyValue(GetterSetterPr
opertyDescriptor.java:75)
at org.dozer.fieldmap.FieldMap.getSrcFieldValue(FieldMap.java:84)
at org.dozer.MappingProcessor.mapField(MappingProcessor.java:275)
at org.dozer.MappingProcessor.map(MappingProcessor.java:248)
at org.dozer.MappingProcessor.map(MappingProcessor.java:197)
at org.dozer.MappingProcessor.map(MappingProcessor.java:187)
at org.dozer.MappingProcessor.map(MappingProcessor.java:133)
at org.dozer.MappingProcessor.map(MappingProcessor.java:128)
at org.dozer.DozerBeanMapper.map(DozerBeanMapper.java:127)
at org.supercsv.io.dozer.CsvDozerBeanWriter.write(CsvDozerBeanWriter.java:132)
at MainAvoidIndexing.writeWithDozerCsvBeanWriter(MainAvoidIndexing.java:68)
at MainAvoidIndexing.main(MainAvoidIndexing.java:29)
答案 0 :(得分:0)
answers
中的SurveyResponse
字段是List
,因此您必须使用索引映射来配置CsvDozerBeanWriter
。索引映射实际上并不是循环的 - 它只是Dozer如何知道要填充List的哪个元素。如果要忽略列,这非常重要 - 它实际上会为该列插入null
元素。
如果您不使用索引映射(并且只使用"answers"
),那么您需要配置一个可以使用List<Answer>
的单元格处理器并将其转换为可以用作CSV。
动态配置字段映射
(不是你问的结果,但我会留下以备将来参考)
不意味着您必须使用静态String数组配置字段映射。您可以使用简单的for循环动态填充数组。例如,
String[] fieldMapping = new String[10];
fieldMapping[0] = "age";
fieldMapping[1] = "consentGiven";
int answerStartIndex = 2;
int answerEndIndex = 8;
for (int i = answerStartIndex; i <= answerEndIndex; i++){
fieldMapping[i] = String.format("answers[%s].questionNo",
i - answerStartIndex);
}
fieldMapping[9] = "age";
这会给你一个fieldMapping:
[age, consentGiven, answers[0].questionNo, answers[1].questionNo,
answers[2].questionNo, answers[3].questionNo, answers[4].questionNo,
answers[5].questionNo, answers[6].questionNo, age]