如何解决Java JAXB 编组:如何避免在使用 XMLAdapter
我有一个 JSON 文件,我正在使用 XML
将其转换为 JAXB
。我正在使用 Jackson 阅读 JSON
然后我使用 XML
过程将它们转换为 JAXB Marshalling
。 JSON
中的元素可以是随机的用户扩展,因此我使用 @JsonAnyGetter
将其存储到 MAP
中,然后我使用适配器将它们转换为 XML 元素。
我只是想知道如何跳过添加 OuterElement
或 Parent 元素,但是我想保留 ÌnnerElementor 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>
以下是我得到的 XML:(当前行为)观察 userextension
标记,该标记由于来自 Extension.class
的变量名称而自动添加。我想知道如何删除此标签但保留内部元素。
<?xml version="1.0"?>
<extension>
<userextension>
<google:g123>
<google:myField>myValue</google:myField>
</google:g123>
</userextension>
</extension>
以下是我的 Extension
类,JSON
将反序列化到该类,并基于 JAXB
将编组以创建 XML:
@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
标记。我只想拥有所有内部元素。
以下是我的主要课程:
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,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) 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);
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。