gpt4 book ai didi

java - 创建 POJO 并从 Map 填充它

转载 作者:行者123 更新时间:2023-12-02 09:02:45 25 4
gpt4 key购买 nike

在运行时,我想创建一个 POJO,其属性与映射的键相同,并用映射的值填充它。
我不知道映射的内容 map 或 POJO 的外观
示例-

Map<String,String> map = new HashMap<>();
map.add("attr1", obj1);
map.add("attr2", obj2);
...

我想从这张 map 创建一个 POJO-

class POJO
{
String attr1;

public void setAttr1(String attr1) {
this.attr1 = attr1;
}

public String getAttr1() {
return attr1;
}

String attr2;

public void setAttr2(String attr2) {
this.attr2 = attr2;
}

public String getAttr2() {
return attr2;
}

.....
}

并填充它。所有这些都应该在运行时发生。类似的东西-

Object object = getPopulatedPOJO(map)

Class type = getPOJOType(map);
Object object = type.newInstance();
object = getPopulatedPOJO(map)

最佳答案

这不是您问题的最终答案。但我希望这能为您提供继续下去的方向。请注意,此方向会在运行时修改字节码指令,并可能导致崩溃和故障。

您可以使用javassist,它是一个字节码操纵器。请查看他们的official site了解更多信息。

需要注意的两件事

  1. In Java, multiple class loaders can coexist and each class loader creates its own name space. Different class loaders can load different class files with the same class name

  2. The JVM does not allow dynamically reloading a class. Once a class loader loads a class, it cannot reload a modified version of that class during runtime. Thus, you cannot alter the definition of a class after the JVM loads it. However, the JPDA (Java Platform Debugger Architecture) provides limited ability for reloading a class

因此您可以通过两种不同的方式实现您想要的目标。

  1. 在运行时创建字节码,编写类,使用自定义类加载器从编写的类创建 pojo。 javassist 可以帮助你,但这对我来说太复杂了,目前无法使用。

  2. 使用 javassist 修改现有类并使用反射来设置值。

对于选项 2(更简单的一种),以下是实现这一目标的方法。

  1. 在类路径中添加 javassist。如果您使用的是 Maven,请在 pom.xml 中添加以下依赖项。
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.21.0-GA</version>
</dependency>
  1. 创建一个您需要使用的虚拟空 pojo 类。我们称之为 Pojo
package com.test;

public class Pojo {
//Nothing in the source file.
}
  • 修改类主体以添加 HashMap 中的字段。这是我如何使用您提供的 map 进行操作的示例。
  •         Map<String, String> map = new HashMap<String, String>();
    map.put("firstname", "John");
    map.put("lastname", "Doe");

    ClassPool cp = ClassPool.getDefault();

    CtClass cc = cp.get("com.test.Pojo");

    // Used for non-primitive data types. If primitive, use CtClass.<inttype, floattype, etc..>
    CtClass strClass = ClassPool.getDefault().get("java.lang.String");

    //Iterate and add all the fields as per the keys in the map
    Iterator<String> iterator = map.keySet().iterator();
    while (iterator.hasNext()) {
    String key = iterator.next();
    CtField field = new CtField(strClass, key, cc);
    field.setModifiers(Modifier.PUBLIC);
    cc.addField(field);
    }

    // Instantiate from the updated class
    Class<Pojo> clazz = cc.toClass();
    Pojo newInstance = clazz.newInstance();

    //Use the map again to set the values using reflection.
    iterator = map.keySet().iterator();
    while (iterator.hasNext()) {
    String key = iterator.next();
    newInstance.getClass().getField(key).set(newInstance, map.get(key));
    }
  • newInstancePojo 的实例,但具有根据映射的键添加的字段并根据映射中的值设置的字段。使用 Jackson ObjectMapper 打印 newInstance 的简单测试会产生此结果。
  • ObjectMapper objMapper = new ObjectMapper();
    String writeValueAsString = objMapper.writeValueAsString(newInstance);
    System.out.println(writeValueAsString);

    {"firstname":"John","lastname":"Doe"}

    希望这有帮助。

    编辑

    如果要添加get/set方法,可以使用javassist中的CtMethod创建方法。但是,您只能使用反射来访问它们,因为这些方法是在运行时添加的。

    关于java - 创建 POJO 并从 Map<String, String> 填充它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60041782/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com