如何让 JAXB 识别不同的 类
How to make JAXB recognize different Classes
我已经实现了 JAXB 来将 XML 数据转换为对象,这里我是这样使用的。
假设注册了一个新用户。所以我必须将数据加载到适当的 class 中以将其存储在数据库中。所以我将其硬编码为 .newInstance(User.Class)
JAXBContext context = JAXBContext.newInstance(User.class);
现在我要做一些雇主相关的工作。
为此,我需要将其作为 .newInstance(Employer.class) 。可以通过复制粘贴相同的 jaxb 转换并将 .newInstance(User.Class) 替换为 .newInstance(Employer.Class)。但我希望将 JAXB 转换为 Util,它可以用于不同的 classes 而无需对各自的 Class
进行硬编码
我有这样的 XML 数据
<User>
<username>user</username>
<password>password</password>
</User>
我尝试做的是,如果我要从 UserController 调用 JaxbUtil.java,我会将其存储为
String className = "User.class";
如果我从 EmployerComtroller 调用它
String className = "Employer.class";
然后在调用方法时,就像
JaxbUtil.jaxbXMLToObject(xmlData,className);
这是我在 JaxbUtil.java
中的 jaxbXMLToObject 方法
public static User jaxbXMLToObject(String xmlData,String className) { //I've passed the xmlString to unmarshaller by StringReader
User user = null;
JAXBContext context = JAXBContext.newInstance(className);
return user; // Ofcourse this is after conversion
}
现在我希望你们能理解我想说的。
1) .newInstance() 不接受字符串
2) 即使我让它识别(不可能,假设),我也必须更改方法声明中的 return 类型。
是否可以在不为每个对象创建单独方法的情况下,使此方法对所有 xml 到不同对象的转换通用?
解法:
String xmlData; // Assume I've xmlData stored as String
Class<?> classType = Class.forName("com.package.model.Employer");
Employer employer = (Employer) JAXBUtil.jaxbXMLToObject(xmlData,classType); //JaxbUtil is the Util class where the below code is saved
public static Object jaxbXMLToObject(String xmlData, Class<?> classType) throws ClassNotFoundException {
Object object = null;
try {
JAXBContext context = JAXBContext.newInstance(classType);
Unmarshaller unmarshaller = context.createUnmarshaller();
StringReader reader = new StringReader(xmlData);
object = (Object) unmarshaller.unmarshal(reader);
} catch (JAXBException e) {
e.printStackTrace();
}
return object;
}
所以我现在可以通过更改每个控制器中的 class 名称来调用该 Util 方法。
编辑: 接受的答案比我上面发布的解决方案标准化得多。如果您必须实施它,请参考已接受的答案。
两个可能的答案:
如果要从 xml 解组到对象,则需要创建
要解组的对象,这就是重点。
如果您想将 xml 文件放入字符串中,则不需要 JAXB。
您将需要使用 ClassLoader
从 class 名称加载真实的 class。然后bootstrap那个class上的JAXBContext
。
更新
How can I make a return type generic? I mean, each class independent
of each other, like User operation have to return User, Employer
operation have to return Employer, but neither User nor Employer is
having interface or extends relationships
如果您可以将参数设置为 Class
而不是 String
那么您可以执行以下操作。来自 jaxbXMLToObject
的 return 类型将是您传入的类型。
public static <T> T jaxbXMLToObject(String xmlData, Class<T> clazz) { //I've passed the xmlString to unmarshaller by StringReader
try {
T result = null;
JAXBContext context = JAXBContext.newInstance(clazz);
Unmarshaller unmarshaller = context.createUnmarshaller();
StreamSource source = new StreamSource(new StringReader(xmlData));
result = unmarshaller.unmarshal(source, clazz).getValue();
return result; // Ofcourse this is after conversion
} catch(JAXBException e) {
// TODO - Handle Exception
}
return null;
}
然后您将可以执行以下操作:
Foo foo = jaxbXMLToObject(xmlData, Foo.class);
Bar bar = jaxbXMLToObject(xmlData, Bar.class);
我已经实现了 JAXB 来将 XML 数据转换为对象,这里我是这样使用的。
假设注册了一个新用户。所以我必须将数据加载到适当的 class 中以将其存储在数据库中。所以我将其硬编码为 .newInstance(User.Class)
JAXBContext context = JAXBContext.newInstance(User.class);
现在我要做一些雇主相关的工作。 为此,我需要将其作为 .newInstance(Employer.class) 。可以通过复制粘贴相同的 jaxb 转换并将 .newInstance(User.Class) 替换为 .newInstance(Employer.Class)。但我希望将 JAXB 转换为 Util,它可以用于不同的 classes 而无需对各自的 Class
进行硬编码我有这样的 XML 数据
<User>
<username>user</username>
<password>password</password>
</User>
我尝试做的是,如果我要从 UserController 调用 JaxbUtil.java,我会将其存储为
String className = "User.class";
如果我从 EmployerComtroller 调用它
String className = "Employer.class";
然后在调用方法时,就像
JaxbUtil.jaxbXMLToObject(xmlData,className);
这是我在 JaxbUtil.java
中的 jaxbXMLToObject 方法public static User jaxbXMLToObject(String xmlData,String className) { //I've passed the xmlString to unmarshaller by StringReader
User user = null;
JAXBContext context = JAXBContext.newInstance(className);
return user; // Ofcourse this is after conversion
}
现在我希望你们能理解我想说的。
1) .newInstance() 不接受字符串
2) 即使我让它识别(不可能,假设),我也必须更改方法声明中的 return 类型。
是否可以在不为每个对象创建单独方法的情况下,使此方法对所有 xml 到不同对象的转换通用?
解法:
String xmlData; // Assume I've xmlData stored as String
Class<?> classType = Class.forName("com.package.model.Employer");
Employer employer = (Employer) JAXBUtil.jaxbXMLToObject(xmlData,classType); //JaxbUtil is the Util class where the below code is saved
public static Object jaxbXMLToObject(String xmlData, Class<?> classType) throws ClassNotFoundException {
Object object = null;
try {
JAXBContext context = JAXBContext.newInstance(classType);
Unmarshaller unmarshaller = context.createUnmarshaller();
StringReader reader = new StringReader(xmlData);
object = (Object) unmarshaller.unmarshal(reader);
} catch (JAXBException e) {
e.printStackTrace();
}
return object;
}
所以我现在可以通过更改每个控制器中的 class 名称来调用该 Util 方法。
编辑: 接受的答案比我上面发布的解决方案标准化得多。如果您必须实施它,请参考已接受的答案。
两个可能的答案:
如果要从 xml 解组到对象,则需要创建 要解组的对象,这就是重点。
如果您想将 xml 文件放入字符串中,则不需要 JAXB。
您将需要使用 ClassLoader
从 class 名称加载真实的 class。然后bootstrap那个class上的JAXBContext
。
更新
How can I make a return type generic? I mean, each class independent of each other, like User operation have to return User, Employer operation have to return Employer, but neither User nor Employer is having interface or extends relationships
如果您可以将参数设置为 Class
而不是 String
那么您可以执行以下操作。来自 jaxbXMLToObject
的 return 类型将是您传入的类型。
public static <T> T jaxbXMLToObject(String xmlData, Class<T> clazz) { //I've passed the xmlString to unmarshaller by StringReader
try {
T result = null;
JAXBContext context = JAXBContext.newInstance(clazz);
Unmarshaller unmarshaller = context.createUnmarshaller();
StreamSource source = new StreamSource(new StringReader(xmlData));
result = unmarshaller.unmarshal(source, clazz).getValue();
return result; // Ofcourse this is after conversion
} catch(JAXBException e) {
// TODO - Handle Exception
}
return null;
}
然后您将可以执行以下操作:
Foo foo = jaxbXMLToObject(xmlData, Foo.class);
Bar bar = jaxbXMLToObject(xmlData, Bar.class);