我在这些论坛上读到了很多答案,还有其他的博客文章,但我似乎无法将这些部分联系起来。
因此,我们从包含映射属性的基本POJO开始。已经确定了如何包装它,但这会返回一些值。我要做的是获取then名称(又称标签),并使其成为有效的XML“属性”。所以我们会得到一些价值。
我发现了一个示例(如果我能再次找到它,将链接),如下所示:
@XmlAnyElement
public List<JAXBElement<String>> getXmlProperties() {
List<JAXBElement<String>> elements = new ArrayList<JAXBElement<String>>();
for (Map.Entry<String, String> property: properties.entrySet())
elements.add(new JAXBElement<String>(new QName(property.getKey()),
String.class, property.getValue()));
return elements;
}
这工作得很好,但我在Bean/Pojo类中使用了它,该类与GWT前端共享,因此不能包含对JAXBElement和QName的引用(需要源代码)。
那么,有没有一种方法可以使用XmlAdapter和JAXBElement/QName/XmlAnyElement dream团队之类的东西获得类似的结果?顺便说一下,如果考虑到这一点,我正在使用RESTEasy。
以下是带有@xmlanyement JAXBElement的论坛帖子:带有JAXB的动态标记名
根据上面列出的解决方案,我加入了这个MapAdapter
,它同时处理封送和解封送过程。
@XmlType
public class MapWrapper{
private List<JAXBElement<String>> properties = new ArrayList<>();
public MapWrapper(){
}
@XmlAnyElement
public List<JAXBElement<String>> getProperties() {
return properties;
}
public void setProperties(List<JAXBElement<String>> properties) {
this.properties = properties;
}
@Override
public String toString() {
return "MapWrapper [properties=" + toMap() + "]";
}
public Map<String, String> toMap(){
//Note: Due to type erasure, you cannot use properties.stream() directly when unmashalling is used.
List<?> props = properties;
return props.stream().collect(Collectors.toMap(MapWrapper::extractLocalName, MapWrapper::extractTextContent));
}
@SuppressWarnings("unchecked")
private static String extractLocalName(Object obj){
Map<Class<?>, Function<? super Object, String>> strFuncs = new HashMap<>();
strFuncs.put(JAXBElement.class, (jaxb) -> ((JAXBElement<String>)jaxb).getName().getLocalPart());
strFuncs.put(Element.class, ele -> ((Element) ele).getLocalName());
return extractPart(obj, strFuncs).orElse("");
}
@SuppressWarnings("unchecked")
private static String extractTextContent(Object obj){
Map<Class<?>, Function<? super Object, String>> strFuncs = new HashMap<>();
strFuncs.put(JAXBElement.class, (jaxb) -> ((JAXBElement<String>)jaxb).getValue());
strFuncs.put(Element.class, ele -> ((Element) ele).getTextContent());
return extractPart(obj, strFuncs).orElse("");
}
private static <ObjType, T> Optional<T> extractPart(ObjType obj, Map<Class<?>, Function<? super ObjType, T>> strFuncs){
for(Class<?> clazz : strFuncs.keySet()){
if(clazz.isInstance(obj)){
return Optional.of(strFuncs.get(clazz).apply(obj));
}
}
return Optional.empty();
}
}
public class MapAdapter extends XmlAdapter<MapWrapper, Map<String, String>>{
@Override
public Map<String, String> unmarshal(MapWrapper v) throws Exception {
return v.toMap();
}
@Override
public MapWrapper marshal(Map<String, String> m) throws Exception {
MapWrapper wrapper = new MapWrapper();
for(Map.Entry<String, String> entry : m.entrySet()){
wrapper.addEntry(new JAXBElement<String>(new QName(entry.getKey()), String.class, entry.getValue()));
}
return wrapper;
}
}
我已经在这里发布了全文(另一篇文章),这里还提供了评论和示例。。
我离答案不远——经过更多的实验,我找到了正确的组合。
为不可映射的返回类型创建包装器类。包装器应该包含/返回List
public class MapWrapper {
@XmlAnyElement
public List<JAXBElement<String>> properties = new ArrayList<JAXBElement<String>>();
}
创建一个向MapWrapper封送的XmlAdapter
public class MapAdapter extends XmlAdapter<MapWrapper, Map<String,String>> {
@Override
public MapWrapper marshal(Map<String,String> m) throws Exception {
MapWrapper wrapper = new MapWrapper();
List<JAXBElement<String>> elements = new ArrayList<JAXBElement<String>>();
for (Map.Entry<String, String> property: m.entrySet()) {
elements.add(new JAXBElement<String>(
new QName(getCleanLabel(property.getKey())),
String.class, property.getValue()));
}
wrapper.elements=elements;
return wrapper;
}
@Override
public Map<String,String> unmarshal(MapWrapper v) throws Exception {
// TODO
throw new OperationNotSupportedException();
}
// Return a lower-camel XML-safe attribute
private String getCleanLabel(String attributeLabel) {
attributeLabel = attributeLabel.replaceAll("[()]", "")
.replaceAll("[^\\w\\s]", "_").replaceAll(" ", "_")
.toUpperCase();
attributeLabel = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL,
attributeLabel);
return attributeLabel;
}
}
使用XmlAdapter注释不可映射类型
@XmlRootElement
public class SomeBean {
@XmlJavaTypeAdapter(MapAdapter.class)
public LinkedHashMap<String, String> getProperties() {
return properties;
}
}
像这样的地图:
My Property 1 My Value 1
My Property 2 My Value 2
结果应该是:
<someBean>
<properties>
<myProperty1>My Value 1</myProperty1>
<myProperty2>My Value 1</myProperty2>
</properties>
</someBean>
希望这能帮助别人!
问题内容: 我有一个div的特定样式表。现在我想使用js动态修改div的一个属性。 我该怎么做? 它是否正确? 问题答案: 几乎是正确的。 由于是JavaScript操作符,因此您实际上不能在属性名称中使用它。如果您正在设置,或者类似的单字,您的代码就可以正常工作。 但是,对于任何带连字符的属性名称,您都需要记住的是,在javascript中,您删除了连字符,并使下一个字母变为大写,因此应为。 还
问题内容: 干草我有这样的元素 不幸的是,此类名称来自电子商务应用程序,无法更改。 我可以在班级名称上打点吗? 喜欢 问题答案: 但是,周围可能会有一些浏览器不支持此功能。
问题内容: 我有一个模块分开的应用程序。有几个实体和CSV模块。CSV模块仅支持struct(Entity),但我想使CSV模块可与任何类型的实体一起使用。现在,它的工作方式如下:Csv模块从通道接收数据并将其严格转换为struct。我如何实现动态返回类型,因此它可以与任何类型的Entity一起使用,而不仅限于 问题答案: 快速/肮脏的解决方案: 返回接口{},但是您最终欺骗了编译器,而类型检查的
我有一个静态的通用FormBuilder超文本标记语言助手方法(HTMLHelper类上的扩展方法),它接受视图模型类型的通用参数,然后当从数据库传递一个或多个字符串属性名称时,生成一个超文本标记语言形式在ASP. NET MVC 5.1 with. NET 4.5中。 我有一个公共方法来生成表单,还有单独的私有方法来生成表单中的“模块”部分,然后渲染其中的每个字段。类型参数从上到下沿此链传递。
问题内容: 使用MVC时,返回即席Json很容易。 我正在使用新的Web API寻找此功能。 由于无法处理匿名类型,因此引发了异常。 我有这个替换此JsonNetFormatter基于 Json.Net 。如果我使用这行得通 但是如果我不返回,我看不到使用Web API的意义,那么最好还是坚持使用香草MVC。如果我尝试使用: 它序列化整个。 谁能指导我找到一种解决方案,在其中可以返回匿名类型? 问
问题内容: 我在这里多次看到类似的问题,但有一个很大的不同。 在其他问题中,返回类型将由参数确定。我想要/需要做的是通过解析后的值确定返回类型。从我收集到的信息来看,以下方法可行: 我只是想确保在我搞砸任何东西之前,它有机会工作。提前致谢。 问题答案: 你做不到 Java返回类型必须是固定的基本类型或对象类。我敢肯定,您能做的最好的事情就是返回一个包装器类型,该包装器类型具有可获取各种可能类型的值