Java 动态创建POJO/bean并使用CGLib设置值
我需要解析文本文件并生成JSON文档。文本文件有一个文本模式,其中包含一个键,该键是一个名称,该值是一个带有标题的TSV大文本 我可以解析文本文件并使用标题生成bean类,现在我想将数据设置为这个生成的bean类。我用反射来做这件事Java 动态创建POJO/bean并使用CGLib设置值,java,algorithm,design-patterns,reflection,javabeans,Java,Algorithm,Design Patterns,Reflection,Javabeans,我需要解析文本文件并生成JSON文档。文本文件有一个文本模式,其中包含一个键,该键是一个名称,该值是一个带有标题的TSV大文本 我可以解析文本文件并使用标题生成bean类,现在我想将数据设置为这个生成的bean类。我用反射来做这件事 Class<?> beanClass = BeanClassGenerator.beanGenerator(k, mapForBeanGeneration); try { Object beanCl
Class<?> beanClass = BeanClassGenerator.beanGenerator(k, mapForBeanGeneration);
try {
Object beanClassObject = beanClass.newInstance();
lines.forEach(line -> {
if (line != null && !line.isEmpty() && !line.equals("null")) {
String[] lineData = line.split("\t");
System.out.println("LineData length :: " + lineData.length);
Method[] methods = beanClass.getMethods();
System.out.println("Methods length :: " + methods.length);
int index = 0;
for (Method m : methods) {
m.setAccessible(true);
if (m.getName().startsWith("set")) {
try {
if ((lineData.length <= index) && lineData[index] != null) {
m.invoke(beanClassObject, lineData[index]);
index++;
} else {
m.invoke(beanClassObject, " ");
}
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
});
ObjectMapper om = new ObjectMapper();
System.out.println(om.writeValueAsString(beanClassObject));
} catch (InstantiationException | IllegalAccessException | JsonProcessingException e) {
e.printStackTrace();
}});
Class beanClass=BeanClassGenerator.BeangGenerator(k,MapForBangeneration);
试一试{
对象beanClassObject=beanClass.newInstance();
行。forEach(行->{
if(line!=null&&!line.isEmpty()&&!line.equals(“null”)){
字符串[]lineData=line.split(“\t”);
System.out.println(“LineData长度::”+LineData.length);
方法[]methods=beanClass.getMethods();
System.out.println(“方法长度::”+方法长度);
int指数=0;
用于(方法m:方法){
m、 setAccessible(true);
if(m.getName().startsWith(“set”)){
试一试{
如果((lineData.length您不需要编写所有逻辑,您可以使用;它提供了一个实用程序方法(在许多其他实用程序中),它将字段名与字段值映射成,并用它填充给定的bean:
BeanUtils.populate(target, fieldNameValueMap);
然后,您需要实现的唯一一件事就是创建fieldNameValueMap
Map
的逻辑;您可以使用以下简单方法:
Map<String, String> createFieldNameValueMap(String headerLine, String valuesLine) {
String[] fieldNames = headerLine.split("\t");
String[] fieldValues = valuesLine.split("\t");
return IntStream.range(0, fieldNames.length)
.mapToObj(Integer::new)
.collect(Collectors.toMap(idx -> fieldNames[idx], idx -> fieldValues[idx]));
}
映射createFieldNameValueMap(字符串标题行、字符串值行){
字符串[]字段名=headerLine.split(“\t”);
String[]fieldValues=valuesLine.split(“\t”);
返回IntStream.range(0,fieldNames.length)
.mapToObj(整数::新)
.collect(Collectors.toMap(idx->fieldNames[idx],idx->fieldValues[idx]);
}
您可以使用以下工作演示来测试此解决方案:
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import org.apache.commons.beanutils.BeanUtils;
import lombok.Data;
public class DynamicBeanUtils {
static Map<String, String> createFieldNameValueMap(String headerLine, String valuesLine) {
String[] fieldNames = headerLine.split("\t");
String[] fieldValues = valuesLine.split("\t");
return IntStream.range(0, fieldNames.length)
.mapToObj(Integer::new)
.collect(Collectors.toMap(idx -> fieldNames[idx], idx -> fieldValues[idx]));
}
public static void main(String[] args) {
String headerLine = "booleanValue\tintValue\tstringValue\tdoubleValue\totherValue";
String valuesLine = "true\t12\tthis bean will be populated\t22.44\ttest string!!!";
Object target = new MyBean();
try {
BeanUtils.populate(target, createFieldNameValueMap(headerLine, valuesLine));
} catch (IllegalAccessException | InvocationTargetException e) {
// HANDLE EXCEPTIONS!
}
System.out.println(target);
}
@Data
public static class MyBean {
private String stringValue;
private double doubleValue;
private int intValue;
private boolean booleanValue;
private String otherValue;
}
}
import java.lang.reflect.InvocationTargetException;
导入java.util.Map;
导入java.util.stream.collector;
导入java.util.stream.IntStream;
导入org.apache.commons.beanutils.beanutils;
导入龙目数据;
公共类DynamicBeanUtils{
静态映射createFieldNameValueMap(字符串标题行、字符串值行){
字符串[]字段名=headerLine.split(“\t”);
String[]fieldValues=valuesLine.split(“\t”);
返回IntStream.range(0,fieldNames.length)
.mapToObj(整数::新)
.collect(Collectors.toMap(idx->fieldNames[idx],idx->fieldValues[idx]);
}
公共静态void main(字符串[]args){
字符串headerLine=“booleanValue\tintValue\tstringValue\tdoubleValue\totherValue”;
String valuesLine=“true\t12\t此bean将被填充\t22.44\t设置字符串!!!”;
对象目标=新的MyBean();
试一试{
填充(target,createFieldNameValueMap(headerLine,valuesLine));
}捕获(IllegalAccessException | InvocationTargetException e){
//处理异常!
}
系统输出打印项次(目标);
}
@资料
公共静态类MyBean{
私有字符串字符串值;
私人双重价值;
私有int值;
私有布尔布尔值;
私有字符串值;
}
}
这是此依赖项的maven存储库页面,因此您可以将其包含在构建中:
我也在这个解决方案中使用了getter/setters/toString,只是为了省去编写getter/setters/toString来测试这个解决方案的麻烦;但是您的解决方案并不需要它
希望这有帮助。您的解决方案太过火了。
您的数据被组织为可变长度数组的数组;
而且不需要一些疯狂的动态类生成解决方案。
作为旁注,
即时类生成并不是天生的疯狂;
在这种情况下使用动态类生成是疯狂的
这样做:
看看你的数据;
其组织如下:
第一:外键
第二:正好一行包含可变数量的空格分隔的内部键数组
第三:包含值的行数
设计解决方案来解决您的问题
读外键。
使用该值创建JSON的外键部分
阅读内部键。
将这些存储在一个数组中;
使用LinkedList,
不是小丑列表(ArrayList)
执行此操作直到下一个空行:
读一行值
编写内部JSON;使用内部键作为此操作的键
跳过空行,直到出现以下情况之一:
如果在文件末尾,则写入JSON的结尾部分
如果读取下一个外键,转到上面的第2行(读取内键)
编写代码
我意识到,与其用复杂的方法创建POJO,不如使用Map
s并使用JacksonObjectMapper
将其转换为JSON。为其他认为这可能是一种有用方法的人发帖
public String convert(Map<String, ? extends Metadata> metadataMap) {
String output = "";
Map<String, List<Map<String, String>>> finalMap = new HashMap<>();
metadataMap.forEach((k, v) -> {
List<Map<String, String>> datamap = new LinkedList<>();
String key = k;
String[] fields = v.getFields();
List<String> lines = v.getLines();
lines.forEach(line -> {
if (line != null && !line.isEmpty() && !line.equals("null")) {
String[] fieldData = line.split("\t",-1);
Map<String, String> eachLineMap = new HashMap<>();
for (int index = 0; index < fields.length; index++) {
if (index < fieldData.length && (fieldData[index] != null && !fieldData[index].isEmpty())) {
eachLineMap.put(fields[index], fieldData[index]);
} else {
eachLineMap.put(fields[index], " ");
}
datamap.add(eachLineMap);
}
}
});
finalMap.put(key, datamap);
});
try {
output = new ObjectMapper().writeValueAsString(finalMap);
}catch(JsonProcessingException e){
e.printStackTrace();
}
return output;
}
公共字符串转换(映射metadataMap){
字符串输出=”;
Map finalMap=newhashmap();
metadataMap.forEach((k,v)->{
List datamap=new LinkedList();
字符串键=k;
String[]fields=v.getFields();
列表行=v.getLines();
行。forEach(行->{
if(line!=null&&!line.isEmpty()&&!line.equals(“null”)){
String[]fieldData=line.split(“\t”,-1);
Map eachLineMap=newhashmap();
for(int index=0;index BeanUtils.populate(target, fieldNameValueMap);
Map<String, String> createFieldNameValueMap(String headerLine, String valuesLine) {
String[] fieldNames = headerLine.split("\t");
String[] fieldValues = valuesLine.split("\t");
return IntStream.range(0, fieldNames.length)
.mapToObj(Integer::new)
.collect(Collectors.toMap(idx -> fieldNames[idx], idx -> fieldValues[idx]));
}
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import org.apache.commons.beanutils.BeanUtils;
import lombok.Data;
public class DynamicBeanUtils {
static Map<String, String> createFieldNameValueMap(String headerLine, String valuesLine) {
String[] fieldNames = headerLine.split("\t");
String[] fieldValues = valuesLine.split("\t");
return IntStream.range(0, fieldNames.length)
.mapToObj(Integer::new)
.collect(Collectors.toMap(idx -> fieldNames[idx], idx -> fieldValues[idx]));
}
public static void main(String[] args) {
String headerLine = "booleanValue\tintValue\tstringValue\tdoubleValue\totherValue";
String valuesLine = "true\t12\tthis bean will be populated\t22.44\ttest string!!!";
Object target = new MyBean();
try {
BeanUtils.populate(target, createFieldNameValueMap(headerLine, valuesLine));
} catch (IllegalAccessException | InvocationTargetException e) {
// HANDLE EXCEPTIONS!
}
System.out.println(target);
}
@Data
public static class MyBean {
private String stringValue;
private double doubleValue;
private int intValue;
private boolean booleanValue;
private String otherValue;
}
}
public String convert(Map<String, ? extends Metadata> metadataMap) {
String output = "";
Map<String, List<Map<String, String>>> finalMap = new HashMap<>();
metadataMap.forEach((k, v) -> {
List<Map<String, String>> datamap = new LinkedList<>();
String key = k;
String[] fields = v.getFields();
List<String> lines = v.getLines();
lines.forEach(line -> {
if (line != null && !line.isEmpty() && !line.equals("null")) {
String[] fieldData = line.split("\t",-1);
Map<String, String> eachLineMap = new HashMap<>();
for (int index = 0; index < fields.length; index++) {
if (index < fieldData.length && (fieldData[index] != null && !fieldData[index].isEmpty())) {
eachLineMap.put(fields[index], fieldData[index]);
} else {
eachLineMap.put(fields[index], " ");
}
datamap.add(eachLineMap);
}
}
});
finalMap.put(key, datamap);
});
try {
output = new ObjectMapper().writeValueAsString(finalMap);
}catch(JsonProcessingException e){
e.printStackTrace();
}
return output;
}