[英]Java JAXB Marshalling: How to avoid adding the XmlElement during the marshalling for elements with XMLAdapter
我有一个 JSON 文件,我正在使用JAXB
XML
我正在使用 Jackson 读取JSON
然后我使用JAXB Marshalling
过程将它们转换为XML
。 JSON
中的元素可以是随机用户扩展,因此我使用@JsonAnyGetter
将其存储到MAP
然后我使用适配器将它们转换为 Z3501BB093D363810B671059B9CFED3F8 元素。
我只是想知道如何跳过添加OuterElement
或 Parent 元素,但是我想保留 ÌnnerElement or Child element. Is there a
or Child element. Is there a
JAXB 的方法,或者我可以做些什么来达到以下预期的结果?
以下是JSON
文件:
{
"google:g123": {
"google:myField": "myValue"
}
}
以下是我想获得的 XML:(预期)
<?xml version="1.0"?>
<extension>
<google:g123>
<google:myField>myValue</google:myField>
</google:g123>
</extension>
以下是我得到的userextension
:(当前行为)观察由于Extension.class
中的变量名而自动添加的用户扩展标签。 我想知道如何删除此标签但保留内部元素。
<?xml version="1.0"?>
<extension>
<userextension>
<google:g123>
<google:myField>myValue</google:myField>
</google:g123>
</userextension>
</extension>
以下是我的Extension
class ,其中JSON
将被反序列化,并基于JAXB
将编组创建 Z13501BB093D9B36:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "extension")
public class Extension {
@XmlJavaTypeAdapter(ExtensionsAdapter.class)
private Map < String, Object > userExtensions;
@JsonAnyGetter
public Map < String, Object > getUserExtensions() {
return userExtensions;
}
@JsonAnySetter
public void setUserExtensions(String key, Object value) {
if (userExtensions == null) {
userExtensions = new HashMap < String, Object > ();
}
userExtensions.put(key, value);
}
}
以下是我的ExtensionAdapter.class
:
public class ExtensionsAdapter extends XmlAdapter<ExtensionWrapper, Map<String, Object>> {
private DocumentBuilder documentBuilder;
public ExtensionsAdapter() throws Exception {
documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
}
public static class ExtensionWrapper {
@XmlAnyElement
List elements;
}
@SuppressWarnings("unchecked")
@Override
public ExtensionWrapper marshal(Map<String, Object> extensions) throws Exception {
if (extensions == null) {
return null;
}
ExtensionWrapper wrapper = new ExtensionWrapper();
List elements = new ArrayList();
for (Map.Entry<String, Object> extension : extensions.entrySet()) {
if (extension.getValue() instanceof Map) {
elements.add(new JAXBElement<ExtensionWrapper>(new QName(getCleanLabel(extension.getKey())), ExtensionWrapper.class, marshal((Map) extension.getValue())));
} else {
elements.add(new JAXBElement<String>(new QName(getCleanLabel(extension.getKey())), String.class, extension.getValue().toString()));
}
}
wrapper.elements = elements;
return wrapper;
}
// Return a XML-safe attribute. Might want to add camel case support
private String getCleanLabel(String attributeLabel) {
attributeLabel = attributeLabel.replaceAll("[()]", "").replaceAll("[^\\w\\s]", "_").replaceAll(" ", "_");
return attributeLabel;
}
@Override
public Map<String, Object> unmarshal(ExtensionWrapper valurType) throws Exception {
throw new NotImplementedException();
}
}
我尝试添加@XmlAnyElement
,但这会导致以下错误: ExtensionWrapper nor any of its super class is known to this context.
@XmlJavaTypeAdapter(ExtensionsAdapter.class)
@XmlAnyElement
private Map<String, Object> userExtensions;
我只想知道如何在编组过程中跳过添加userExtension
标记。 我只想拥有所有的内在元素。
以下是我的主要 class:
public class Main
{
public static void main(String[] args) {
//jsonStream is the input json which I am reading from a file
final JsonParser jsonParser = jsonFactory.createParser(jsonStream);
jsonParser.setCodec(new ObjectMapper());
final ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
final JsonNode jsonNode = jsonParser.readValueAsTree();
final Extension eventInfo = objectMapper.treeToValue(jsonNode, Extension.class);
JAXBContext context = JAXBContext.newInstance(Extension.class);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
marshaller.marshal(((XmlSupportExtension) eventInfo).xmlSupport(), System.out);
}
}
我能够使用@XmlAnyElement(lax = true)
来做到这一点。 发布答案,以便将来寻找类似答案并且不必浪费时间尝试研究的人有用。
我创建了一个附加字段:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "extension")
public class Extension {
//Old field used only for getting value from JSON
private Map < String, Object > userExtensions;
//New Field which will be added to my XML
@XmlElement(lax=true)
private Object[] xmlExtensions;
@JsonAnyGetter
public Map < String, Object > getUserExtensions() {
return userExtensions;
}
@JsonAnySetter
public void setUserExtensions(String key, Object value) {
if (userExtensions == null) {
userExtensions = new HashMap < String, Object > ();
}
userExtensions.put(key, value);
}
}
我没有将此元素添加到我的propOder
中。
然后我使用 a 方法填充从userExtension
到XmlExtension
的字段:
private Object[] extensionBuilder(Map<String, Object> extensions) {
if (extensions == null) {
return null;
}
return extensions.entrySet().stream().map(extension -> {
if (extension.getValue() instanceof Map) {
// return new JAXBElement<JAXBElement>(new QName(getCleanLabel(extension.getKey())), JAXBElement.class,
// (JAXBElement) extensionBuilder((Map) extension.getValue())[0]);
final Object[] result = extensionBuilder((Map) extension.getValue());
return Arrays.stream(result)
.map(innerExtension -> new JAXBElement<JAXBElement>(new QName(getCleanLabel(extension.getKey())), JAXBElement.class,
(JAXBElement) innerExtension))
.collect(Collectors.toList());
} else {
return Arrays
.asList(new JAXBElement<String>(new QName(getCleanLabel(extension.getKey())), String.class, extension.getValue().toString()));
}
}).flatMap(List::stream).toArray(Object[]::new);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.