【发布时间】:2018-01-13 02:03:28
【问题描述】:
我需要获取 JSON 输入 Pojo 实例,并且我正在使用 Jackson 2 库及以下 readValue 方法可以使用 typeReference 反序列化:
POJO_ClassName p = mapper.readValue(new TypeReference< POJO_ClassName >() {});
但问题是POJO 是在运行时动态创建和加载的,我如何将JSON 转换为POJO 实例/对象,因为我没有上述语句的完全限定类(POJO_ClassName)名称?
注意:我使用jsonSchema2pojo 库在运行时生成POJO 类。
这是代码 sn-p,我用于在运行时为 JSON 生成 POJO
并尝试
String classPath="com.EnrichmentService.Thread72";
String classLocation = System.getProperty("user.dir")
+ "/src/main/java"; JCodeModel codeModel = new JCodeModel();
final RuleFactory ruleFactory = new RuleFactory(config,
new Jackson2Annotator(config), new SchemaStore());
final SchemaMapper mapperSchema = new SchemaMapper(ruleFactory,
new SchemaGenerator());
mapperSchema.generate(codeModel, "EsRootDoc",classPath, json);
codeModel.build(new File(classLocation)); // generates pojo classes
// Till above jsonSchema2Pojo pojo generation all Good !!
// EsRootDoc instance is needed for further drools drl validations.
com.EnrichmentService.Thread72.EsRootDoc p = mapper.readValue(new TypeReference<com.EnrichmentService.Thread72.EsRootDoc>() {});
// see alternative way as well in my 24Aug17 edit at the end of this question
但由于com.EnrichmentService.Thread72.EsRootDoc 尚未生成,编译器会出错到找不到类。
要点:
1) 在运行时迭代生成相同的 Pojo 类,但随着 JSON 输入的每次变化具有不同的属性。
2) 甚至尝试过 对象 pojo =mapper.readValue(json,Class.forName("com.EnrichmentService.Thread72.EsRootDoc"));因为 class.forName 不会替换现有的类!
Edit 24 Aug17 - 这是我的自定义类加载器:
注意:Indexer 是在运行时加载动态 EsRootDoc/POJO 类的类。
static class TestClassLoader extends ClassLoader {
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
if (name.equals("com.EnrichmentService.Thread72.EsRootDoc")) {
try {
InputStream is = Indexer.class.getClassLoader().getResourceAsStream("com/EnrichmentService/Thread72/EsRootDoc.class");
byte[] buf = new byte[is.available()];
int len = is.read(buf);
Class<?> c=defineClass(name, buf, 0, len);
resolveClass(c);
return c;
} catch (IOException e) {
throw new ClassNotFoundException("", e);
}
}
return getParent().loadClass(name);
}
}
我尝试过使用上面的 TestClassLoader 自定义类加载器作为替代方式是这样的:
Class cls = new TestClassLoader().loadClass("com.EnrichmentService.Thread72.EsRootDoc");
Object obj = cls.newInstance();
cls.getMethod("getCrawlerSource").invoke(obj);
p=mapper.readValue(json, cls); // but here i am getting the same deserialization exception as earlier.
引用了一个旧答案@How to replace classes in a running application in java ?
Edit2:2017 年 8 月 24 日 stackTrace 面临的异常在这里:https://pastebin.com/ckCu2uWx
【问题讨论】:
-
我觉得自定义类加载器可以解决这个问题,但问题是大多数类加载器示例我只发现使用自定义类加载器和使用反射调用方法的第一个加载类,但在我的情况下我没有想要调用我的反射方法,但想要 pojo 类的 pojo 实例而不是流口水规则引擎会话。例如:concretepage.com/java/custom-classloader-java-example
-
我对 jsonSchema2pojo 的理解是它生成(通过 JCodeModel)java 源代码,而不是字节码(我弄错了吗?)。您在哪里/何时编译该源代码? (或者这是问题的一部分?)
-
好的,谢谢,我想我明白了,您已经负责编译这些生成的源代码并加载类,您只需要帮助了解如何将 Jackson 与动态加载的类一起使用(如标题中所说的 cleary )。
-
你试过类似
Object pojo = new ObjectMapper().readValue(json, Class.forName("com.acme.Pojo"));的东西吗? -
嗨 Hugues 。如果是 Object pojo = new ObjectMapper().readValue(json, Class.forName("com.acme.Pojo"));同样,我仍然遇到“com.fasterxml.jackson.databind.JsonMappingException:无法反序列化..”问题。作为现在的更改,我尝试使用您建议的工作流程,并且我没有创建默认的空白 pojo 类,也没有在我的代码中的任何地方使用 pojo 类导入语句或完全限定的类名。但是对于上面的语句得到异常。
标签: java json jackson jsonschema2pojo