opencsv 在集合的开始和结束处添加分隔符
opencsv add delimiter at start and end for collection
我正在尝试通过 opencsv 导出一个 bean,但在导出结构中遇到了一个小问题。
我有几个像这样的专栏
@CsvBindAndSplitByPosition(position = 16, splitOn = "\|", converter = MultiAttributeValueConverter.class, elementType = MultiAttributeValue.class, writeDelimiter = "|")
private List<MultiAttributeValue> attributes;
按预期工作并提供以下结果
...,"attribute1=value|attribute2=value2|attribute3=value3",...
我需要稍微不同的输出
...,"|attribute1=value|attribute2=value2|attribute3=value3|",...
我需要前导和尾部 |对于这些领域。
目前我不知道如何添加这些具有任何默认功能或在哪里添加它。
对任何输入或提示感到满意
在关于 MultivValueAttribute 的评论信息中按要求编辑
目前无法访问代码,所以更多的是松散的描述,尽管它不应该影响我的情况,因为我会遇到与简单字符串相同的问题
class MultivValueAttribute {
String name;
String value;
...
}
Converter:
return name+value;
虽然不太好,但我确实找到了使用自定义绑定转换器的解决方案:
public class CustomBindingConverter<T, I> extends AbstractBeanField<T, I>
{
private CustomFormatBeanFieldSplit<T, I> myConvert = null;
@Override
public void setField(Field field)
{
// TODO Auto-generated method stub
super.setField(field);
if (field.isAnnotationPresent(CsvBindAndSplitByPosition.class))
{
CsvBindAndSplitByPosition annotation = field.getAnnotation(CsvBindAndSplitByPosition.class);
String fieldLocale = annotation.locale();
String fieldWriteLocale = annotation.writeLocaleEqualsReadLocale() ? fieldLocale : annotation.writeLocale();
Class<?> elementType = annotation.elementType();
CsvConverter converter = determineConverter(field, elementType, fieldLocale, fieldWriteLocale,
annotation.converter());
myConvert = new CustomFormatBeanFieldSplit<>(getType(), field, annotation.required(), errorLocale,
converter, annotation.splitOn(), annotation.writeDelimiter(), annotation.collectionType(),
annotation.elementType(), annotation.capture(), annotation.format());
}
}
@Override
protected Object convert(String value) throws CsvDataTypeMismatchException, CsvConstraintViolationException
{
return myConvert.convert(value);
}
@Override
protected String convertToWrite(Object value) throws CsvDataTypeMismatchException, CsvRequiredFieldEmptyException
{
// TODO Auto-generated method stub
return myConvert.convertToWrite(value);
}
protected CsvConverter determineConverter(Field field, Class<?> elementType, String locale, String writeLocale,
Class<? extends AbstractCsvConverter> customConverter) throws CsvBadConverterException
{
CsvConverter converter;
// A custom converter always takes precedence if specified.
if (customConverter != null && !customConverter.equals(AbstractCsvConverter.class))
{
try
{
converter = customConverter.newInstance();
}
catch(IllegalAccessException | InstantiationException oldEx)
{
CsvBadConverterException newEx = new CsvBadConverterException(customConverter,
String.format(ResourceBundle.getBundle(ICSVParser.DEFAULT_BUNDLE_NAME, errorLocale)
.getString("custom.converter.invalid"),
customConverter.getCanonicalName()));
newEx.initCause(oldEx);
throw newEx;
}
converter.setType(elementType);
converter.setLocale(locale);
converter.setWriteLocale(writeLocale);
converter.setErrorLocale(errorLocale);
}
// Perhaps a date instead
else if (field.isAnnotationPresent(CsvDate.class))
{
CsvDate annotation = field.getAnnotation(CsvDate.class);
String readFormat = annotation.value();
String writeFormat = annotation.writeFormatEqualsReadFormat() ? readFormat : annotation.writeFormat();
String readChrono = annotation.chronology();
String writeChrono = annotation.writeChronologyEqualsReadChronology() ? readChrono
: annotation.writeChronology();
converter = new ConverterDate(elementType, locale, writeLocale, errorLocale, readFormat, writeFormat,
readChrono, writeChrono);
}
// Or a number
else if (field.isAnnotationPresent(CsvNumber.class))
{
CsvNumber annotation = field.getAnnotation(CsvNumber.class);
String readFormat = annotation.value();
String writeFormat = annotation.writeFormatEqualsReadFormat() ? readFormat : annotation.writeFormat();
converter = new ConverterNumber(elementType, locale, writeLocale, errorLocale, readFormat, writeFormat);
}
// or a Currency
else if (elementType.equals(java.util.Currency.class))
{
converter = new ConverterCurrency(errorLocale);
}
// Or an enumeration
else if (elementType.isEnum())
{
converter = new ConverterEnum(elementType, locale, writeLocale, errorLocale);
}
// Otherwise a primitive
else
{
converter = new ConverterPrimitiveTypes(elementType, locale, writeLocale, errorLocale);
}
return converter;
}
}
以及对 BeanFieldSplitConverter 的修改:
public class CustomFormatBeanFieldSplit<T, I> extends BeanFieldSplit<T, I>
{
String writeFormat;
String writeDelimiter;
public CustomFormatBeanFieldSplit(Class<?> type, Field field, boolean required, Locale errorLocale,
CsvConverter converter, String splitOn, String writeDelimiter,
Class<? extends Collection> collectionType, Class<?> elementType, String capture, String format)
{
super(type, field, required, errorLocale, converter, splitOn, writeDelimiter, collectionType, elementType, capture,
format);
this.writeFormat = format;
this.writeDelimiter = writeDelimiter;
}
@Override
protected String convertToWrite(Object value)
throws CsvDataTypeMismatchException {
String retval = StringUtils.EMPTY;
if(value != null) {
@SuppressWarnings("unchecked") Collection<Object> collection = (Collection<Object>) value;
String[] convertedValue = new String[collection.size()];
int i = 0;
for(Object o : collection) {
convertedValue[i] = converter.convertToWrite(o);
if(StringUtils.isNotEmpty(this.writeFormat)
&& StringUtils.isNotEmpty(convertedValue[i])) {
convertedValue[i] = String.format(this.writeFormat, convertedValue[i]);
}
i++;
}
String coreValue = StringUtils.join(convertedValue, writeDelimiter);
if(StringUtils.isEmpty(coreValue)) {
return coreValue;
}
retval = writeDelimiter + coreValue + writeDelimiter;
}
return retval;
}
@Override
protected Object convert(String value) throws CsvDataTypeMismatchException, CsvConstraintViolationException
{
// TODO Auto-generated method stub
return super.convert(value);
}
}
我正在尝试通过 opencsv 导出一个 bean,但在导出结构中遇到了一个小问题。
我有几个像这样的专栏
@CsvBindAndSplitByPosition(position = 16, splitOn = "\|", converter = MultiAttributeValueConverter.class, elementType = MultiAttributeValue.class, writeDelimiter = "|")
private List<MultiAttributeValue> attributes;
按预期工作并提供以下结果
...,"attribute1=value|attribute2=value2|attribute3=value3",...
我需要稍微不同的输出
...,"|attribute1=value|attribute2=value2|attribute3=value3|",...
我需要前导和尾部 |对于这些领域。 目前我不知道如何添加这些具有任何默认功能或在哪里添加它。
对任何输入或提示感到满意
在关于 MultivValueAttribute 的评论信息中按要求编辑 目前无法访问代码,所以更多的是松散的描述,尽管它不应该影响我的情况,因为我会遇到与简单字符串相同的问题
class MultivValueAttribute {
String name;
String value;
...
}
Converter:
return name+value;
虽然不太好,但我确实找到了使用自定义绑定转换器的解决方案:
public class CustomBindingConverter<T, I> extends AbstractBeanField<T, I>
{
private CustomFormatBeanFieldSplit<T, I> myConvert = null;
@Override
public void setField(Field field)
{
// TODO Auto-generated method stub
super.setField(field);
if (field.isAnnotationPresent(CsvBindAndSplitByPosition.class))
{
CsvBindAndSplitByPosition annotation = field.getAnnotation(CsvBindAndSplitByPosition.class);
String fieldLocale = annotation.locale();
String fieldWriteLocale = annotation.writeLocaleEqualsReadLocale() ? fieldLocale : annotation.writeLocale();
Class<?> elementType = annotation.elementType();
CsvConverter converter = determineConverter(field, elementType, fieldLocale, fieldWriteLocale,
annotation.converter());
myConvert = new CustomFormatBeanFieldSplit<>(getType(), field, annotation.required(), errorLocale,
converter, annotation.splitOn(), annotation.writeDelimiter(), annotation.collectionType(),
annotation.elementType(), annotation.capture(), annotation.format());
}
}
@Override
protected Object convert(String value) throws CsvDataTypeMismatchException, CsvConstraintViolationException
{
return myConvert.convert(value);
}
@Override
protected String convertToWrite(Object value) throws CsvDataTypeMismatchException, CsvRequiredFieldEmptyException
{
// TODO Auto-generated method stub
return myConvert.convertToWrite(value);
}
protected CsvConverter determineConverter(Field field, Class<?> elementType, String locale, String writeLocale,
Class<? extends AbstractCsvConverter> customConverter) throws CsvBadConverterException
{
CsvConverter converter;
// A custom converter always takes precedence if specified.
if (customConverter != null && !customConverter.equals(AbstractCsvConverter.class))
{
try
{
converter = customConverter.newInstance();
}
catch(IllegalAccessException | InstantiationException oldEx)
{
CsvBadConverterException newEx = new CsvBadConverterException(customConverter,
String.format(ResourceBundle.getBundle(ICSVParser.DEFAULT_BUNDLE_NAME, errorLocale)
.getString("custom.converter.invalid"),
customConverter.getCanonicalName()));
newEx.initCause(oldEx);
throw newEx;
}
converter.setType(elementType);
converter.setLocale(locale);
converter.setWriteLocale(writeLocale);
converter.setErrorLocale(errorLocale);
}
// Perhaps a date instead
else if (field.isAnnotationPresent(CsvDate.class))
{
CsvDate annotation = field.getAnnotation(CsvDate.class);
String readFormat = annotation.value();
String writeFormat = annotation.writeFormatEqualsReadFormat() ? readFormat : annotation.writeFormat();
String readChrono = annotation.chronology();
String writeChrono = annotation.writeChronologyEqualsReadChronology() ? readChrono
: annotation.writeChronology();
converter = new ConverterDate(elementType, locale, writeLocale, errorLocale, readFormat, writeFormat,
readChrono, writeChrono);
}
// Or a number
else if (field.isAnnotationPresent(CsvNumber.class))
{
CsvNumber annotation = field.getAnnotation(CsvNumber.class);
String readFormat = annotation.value();
String writeFormat = annotation.writeFormatEqualsReadFormat() ? readFormat : annotation.writeFormat();
converter = new ConverterNumber(elementType, locale, writeLocale, errorLocale, readFormat, writeFormat);
}
// or a Currency
else if (elementType.equals(java.util.Currency.class))
{
converter = new ConverterCurrency(errorLocale);
}
// Or an enumeration
else if (elementType.isEnum())
{
converter = new ConverterEnum(elementType, locale, writeLocale, errorLocale);
}
// Otherwise a primitive
else
{
converter = new ConverterPrimitiveTypes(elementType, locale, writeLocale, errorLocale);
}
return converter;
}
}
以及对 BeanFieldSplitConverter 的修改:
public class CustomFormatBeanFieldSplit<T, I> extends BeanFieldSplit<T, I>
{
String writeFormat;
String writeDelimiter;
public CustomFormatBeanFieldSplit(Class<?> type, Field field, boolean required, Locale errorLocale,
CsvConverter converter, String splitOn, String writeDelimiter,
Class<? extends Collection> collectionType, Class<?> elementType, String capture, String format)
{
super(type, field, required, errorLocale, converter, splitOn, writeDelimiter, collectionType, elementType, capture,
format);
this.writeFormat = format;
this.writeDelimiter = writeDelimiter;
}
@Override
protected String convertToWrite(Object value)
throws CsvDataTypeMismatchException {
String retval = StringUtils.EMPTY;
if(value != null) {
@SuppressWarnings("unchecked") Collection<Object> collection = (Collection<Object>) value;
String[] convertedValue = new String[collection.size()];
int i = 0;
for(Object o : collection) {
convertedValue[i] = converter.convertToWrite(o);
if(StringUtils.isNotEmpty(this.writeFormat)
&& StringUtils.isNotEmpty(convertedValue[i])) {
convertedValue[i] = String.format(this.writeFormat, convertedValue[i]);
}
i++;
}
String coreValue = StringUtils.join(convertedValue, writeDelimiter);
if(StringUtils.isEmpty(coreValue)) {
return coreValue;
}
retval = writeDelimiter + coreValue + writeDelimiter;
}
return retval;
}
@Override
protected Object convert(String value) throws CsvDataTypeMismatchException, CsvConstraintViolationException
{
// TODO Auto-generated method stub
return super.convert(value);
}
}