我要求我使用SuperCSV读取csv文件并映射到对象。
SuperCSV有一个要求,如果头部指定了一个字段名称“firstName”,它需要在类中使用setFirstName()方法,否则会引发异常。
现在,如果我使用Groovy bean,那么我不需要声明所有这些方法只是声明变量应该适用于SuperCSV。
但我一直在寻找一个更加动态的解决方案,我们甚至不需要声明这些变量。
例如,只需在飞行中创建一个对象,并使用groovy的动态方法创建功能,SuperCSV将能够找到设置者。
我查看了各种选项,例如Expando,ExpandoMetaClass,但这些选项并没有达到我的目的。
任何答案都将不胜感激。
以下代码片段对我有用,可以帮助减少大量代码和不必要的逻辑:
static def testBeanReader()
{
ICsvBeanReader beanReader = null;
try
{
beanReader = new CsvBeanReader(new FileReader("src/test.csv"),
CsvPreference.STANDARD_PREFERENCE);
}
catch(Exception e)
{
}
final String[] header = VirtualObject.getHeaders();
final CellProcessor[] processors = VirtualObject.getProcessors();
//Class c1 = createNewClass()
//String s = createClass()
def list = ["name", "age"]
def c = (new GroovyShell().evaluate(createClass(list)) as Class)
//println(c.methods.grep {it.name.startsWith("get")})
GroovyObject groovyObject = (GroovyObject)(beanReader.read(c, header, processors))
Object[] args = {};
println(groovyObject.getProperty("name"))
}
static def createClass(def list)
{
String classDeclaration = "\nclass Test {\n"
list.each
{
classDeclaration+="def $it\n"
}
classDeclaration+= """
}
return Test.class
"""
return classDeclaration
}
这对于supercsv的东西,但可以用于语法
几乎没有变化的通用java对象答案 0 :(得分:2)
不能使用Groovy shell来动态构造这些类。
def c = (new GroovyShell().evaluate("""
class Test {
def fileName // list properties here
}
return Test.class
""") as Class)
println(c.methods.grep {it.name.startsWith("set")})
def m = (c as Class).getMethod("setFileName", [Object] as Class[])
// We, and I suppose SuperCSV, can access method via Reflexion API
它不安全,但它会动态创建Java兼容类。
我不熟悉SuperCSV,但我认为当Expando或MetaClass解决方案使用Groovy元对象协议时,它应该像反射一样使用smth。
GroovyShell(或GroovyClassLoader)将能够创建正常的类,具有工作的Reflexion。
已编辑:说明生成的类的动态特性。我们首先创建类源(正如我们所希望的,从运行时信息中,来自CSV标题),然后使用它。
def createClassDeclaration()
{
String classDeclaration = "\nclass Test {\n"
// Here you can use your runtime information, schema, array of fields, getted from any source.
10.times {
classDeclaration+="def field$it\n" // declares def field1, field2, ... etc
}
classDeclaration += """
}
return Test.class
"""
println(classDeclaration)
return classDeclaration
}
def compile(String s)
{
def c = (new GroovyShell().evaluate(s) as Class)
def m = (c as Class).getMethod("setField1", [Object] as Class[])
assert m
println(c.methods.grep {it.name.startsWith("set")})
}
compile(createClassDeclaration())