GVKun编程网logo

java – 使用JAXB根据属性创建引用对象(java 根据类型创建对象)

7

在本文中,我们将为您详细介绍java–使用JAXB根据属性创建引用对象的相关知识,并且为您解答关于java根据类型创建对象的疑问,此外,我们还会提供一些关于Java/JAXB:将XML属性解组为特定的

在本文中,我们将为您详细介绍java – 使用JAXB根据属性创建引用对象的相关知识,并且为您解答关于java 根据类型创建对象的疑问,此外,我们还会提供一些关于Java / JAXB:将XML属性解组为特定的Java对象属性、Java Unmarshal使用JAXB的对象列表、java – 使用JAXB创建不可变对象、java – 使用JAXB处理丢失的节点的有用信息。

本文目录一览:

java – 使用JAXB根据属性创建引用对象(java 根据类型创建对象)

java – 使用JAXB根据属性创建引用对象(java 根据类型创建对象)

考虑以下xml:

<Config>
    <Paths>
        <Path reference="WS_License"/>
    </Paths>

    <Steps>
        <Step id="WS_License" title="License Agreement" />
    </Steps>
</Config>

以下JAXB类:

public class Path {

    private String _reference;

    public String getReference() {
        return _reference;
    }

    @XmlAttribute
    public void setReference( String reference ) {
        _reference = reference;
    }

}

public class Step {

    private String _id;
    private String _title;

    public String getId() {
        return _id;
    }

    @XmlAttribute
    public void setId( String id ) {
        _id = id;
    }

    public String getTitle() {
        return _title;
    }

    @XmlAttribute
    public void setTitle( String title ) {
        _title = title;
    }

}

我不想将引用作为String存储在Path对象中,而是将其作为Step对象保存.这些对象之间的链接是reference和id属性. @XMLJavaTypeAdapter属性是否可行?任何人都可以如此善良地提供正确用法的例子吗?

谢谢!

编辑:

我也想用元素做同样的技术.

考虑以下xml:

<Config>
    <Step id="WS_License" title="License Agreement">
        <DetailPanelReference reference="DP_License" />
    </Step>

    <DetailPanels>
        <DetalPanel id="DP_License" title="License Agreement" />
    </DetailPanels>
</Config>

以下JAXB类:

@XmlAccessorType(XmlAccesstype.FIELD)
public class Step {

    @XmlID
    @XmlAttribute(name="id")
    private String _id;

    @XmlAttribute(name="title")
    private String _title;

    @XmlIDREF
    @XmlElement(name="DetailPanelReference", type=DetailPanel.class)
    private DetailPanel[] _detailPanels; //Doesn't seem to work

}

@XmlAccessorType(XmlAccesstype.FIELD)
public class DetailPanel {

    @XmlID
    @XmlAttribute(name="id")
    private String _id;

    @XmlAttribute(name="title")
    private String _title;

}

Step-object中的属性_detailPanels为空,链接似乎不起作用.是否有任何选项可以在不创建仅包含对DetailPanel的引用的新JAXB对象的情况下创建链接?

再次感谢 : )!

解决方法:

您可以使用@XmlID将属性映射为键,使用@XmlIDREF将引用映射到此用例的键.

@XmlAccessorType(XmlAccesstype.FIELD)
public class Step {

    @XmlID
    @XmlAttribute
    private String _id;

}

路径

@XmlAccessorType(XmlAccesstype.FIELD)
public class Path {

    @XmlIDREF
    @XmlAttribute
    private Step _reference;

}

欲获得更多信息

> http://blog.bdoughan.com/2010/10/jaxb-and-shared-references-xmlid-and.html

UPDATE

Thanks! I Completely missed your article. I’ve extended my question,
do you have any clue if this is possible too? I do not want to create
a class with only holding the reference, I’d like to store it inside
the step class.

注意:我是EclipseLink JAXB (MOXy)领导者,也是JAXB (JSR-222)专家组的成员.

如果您使用MOXy作为JAXB(JSR-222)提供程序,那么您可以将@XmlPath批注用于您的用例.

import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlPath;

@XmlAccessorType(XmlAccesstype.FIELD)
public class Step {

    @XmlID
    @XmlAttribute
    private String id;

    @XmlPath("DetailPanelReference/@reference")
    @XmlIDREF
    // private List<DetailPanel> _detailPanels; // WORKS
    private DetailPanel[] _detailPanels; // See bug:  http://bugs.eclipse.org/399293

}

欲获得更多信息

> http://bugs.eclipse.org/399293
> http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
> http://blog.bdoughan.com/2010/07/xpath-based-mapping.html

Java / JAXB:将XML属性解组为特定的Java对象属性

Java / JAXB:将XML属性解组为特定的Java对象属性

有一个丑陋的XML文件必须解组:

<?xml version="1.0" ?><configuration>    <section name="default_options">        <value name="default_port">8081</value>        <value name="log_level">WARNING</value>    </section>    <section name="custom_options">        <value name="memory">64M</value>        <value name="compatibility">yes</value>    </section></configuration>

产生的Java对象应为:

public class DefaultOptions {    private int defaultPort;    private String logLevel;    // etc...}public class CustomOptions {    private String memory;    private String compatibility;    // etc...}

这个问题的答案非常接近,但我不知道最终的解决方案。

答案1

小编典典

怎么样?

介绍一个称为选项的通用超类:

import javax.xml.bind.annotation.XmlAttribute;public abstract class Options {    private String name;    @XmlAttribute    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }}

然后在带有选项列表的类(在本示例中为Configuration)上,在该属性上指定一个@XmlJavaTypeAdapter:

import java.util.ArrayList;import java.util.List;import javax.xml.bind.annotation.XmlRootElement;import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;@XmlRootElementpublic class Configuration {    private List<Options> section = new ArrayList<Options>();    @XmlJavaTypeAdapter(OptionsAdapter.class)    public List<Options> getSection() {        return section;    }    public void setSection(List<Options> section) {        this.section = section;    }}

XmlAdapter看起来像这样:

import javax.xml.bind.annotation.adapters.XmlAdapter;public class OptionsAdapter extends XmlAdapter<AdaptedOptions, Options> {    @Override    public Options unmarshal(AdaptedOptions v) throws Exception {        if("default_options".equals(v.name)) {            DefaultOptions options = new DefaultOptions();            options.setName(v.getName());            options.setDefaultPort(Integer.valueOf(v.map.get("default_port")));            options.setLogLevel(v.map.get("log_level"));            return options;        } else {            CustomOptions options = new CustomOptions();            options.setName(v.getName());            options.setCompatibility(v.map.get("compatibility"));            options.setMemory(v.map.get("memory"));            return options;        }    }    @Override    public AdaptedOptions marshal(Options v) throws Exception {        AdaptedOptions adaptedOptions = new AdaptedOptions();        adaptedOptions.setName(v.getName());        if(DefaultOptions.class == v.getClass()) {            DefaultOptions options = (DefaultOptions) v;            adaptedOptions.map.put("default_port", String.valueOf(options.getDefaultPort()));            adaptedOptions.map.put("log_level", options.getLogLevel());        } else {            CustomOptions options = (CustomOptions) v;            adaptedOptions.map.put("compatibility", options.getCompatibility());            adaptedOptions.map.put("memory", options.getMemory());        }        return adaptedOptions;    }}

AdaptedOptions看起来像:

import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.Map.Entry;import javax.xml.bind.Marshaller;import javax.xml.bind.Unmarshaller;import javax.xml.bind.annotation.XmlAttribute;import javax.xml.bind.annotation.XmlElement;import javax.xml.bind.annotation.XmlValue;public class AdaptedOptions extends Options {    @XmlAttribute String name;    @XmlElement List<Value> value = new ArrayList<Value>();    Map<String, String> map = new HashMap<String, String>();    public void beforeMarshal(Marshaller marshaller) {        for(Entry<String, String> entry : map.entrySet()) {            Value aValue = new Value();            aValue.name = entry.getKey();            aValue.value = entry.getValue();            value.add(aValue);        }    }    public void afterUnmarshal(Unmarshaller unmarshaller, Object parent) {        for(Value aValue : value) {            map.put(aValue.name, aValue.value);        }    }    private static class Value {        @XmlAttribute String name;        @XmlValue String value;    }}

Java Unmarshal使用JAXB的对象列表

Java Unmarshal使用JAXB的对象列表

我有看起来像下面的XML:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ObjectList>
  <object attributeOne="somedate" attributeTwo="false" attributeThree="id" attributeFour="true"/>
  <object attributeOne="somedate" attributeTwo="false" attributeThree="id" attributeFour="true"/>
  <object attributeOne="somedate" attributeTwo="false" attributeThree="id" attributeFour="true"/>
  <object attributeOne="somedate" attributeTwo="false" attributeThree="id" attributeFour="true"/>
  <object attributeOne="somedate" attributeTwo="false" attributeThree="id" attributeFour="true"/>
</ObjectList>

我有一个如下的ObjectList类:

@XmlRootElement
public class ObjectList {

    @XmlElementWrapper(name = "ObjectList")
    @XmlElement(name = "Object")
    private ArrayList<Object> ObjectList;

    public ArrayList<Object> getObjectList() {
        return ObjectList;
    }

    public void setObjectList(ArrayList<Object> objectList) {
        ObjectList = objectList;
    }
}

还有一个对象类,如下所示:

@XmlRootElement(name = "Object")
public class Object {

    Date attributeOne;
    boolean attritbuteTwo;
    String attributeThree;
    boolean attributeFour;

    @XmlAttribute
    public Date getAttributeOne() {
        return attributeOne;
    }
    public void setAttributeOne(Date attributeOne) {
        this.attributeOne = attributeOne;
    }

    @XmlAttribute
    public boolean isAttributeTwo() {
        return attritbuteTwo;
    }
    public void setAttributeTwo(boolean attritbuteTwo) {
        this.AttributeTwo = AttributeTwo;
    }

    @XmlAttribute
    public String getAttributeThree() {
        return attributeThree;
    }
    public void setAttributeThree(String attributeThree) {
        this.attributeThree = attributeThree;
    }

    @XmlAttribute
    public boolean isAttributeFour() {
        return attributeFour;
    }
    public void setAttributeFour(boolean attributeFour) {
        this.attributeFour = attributeFour;
    }
}

当我尝试使用以下代码将xml解组为和对象时:

JAXBContext jaxbContext = JAXBContext.newInstance(ObjectList.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();

RESTResponse response = getObjects();

ObjectList objects = (ObjectList) unmarshaller.unmarshal(new StringReader(response.getResponseBody()));

我收到以下错误:

javax.xml.bind.UnmarshalException:意外元素(uri:“”,本地:“ ObjectList”)。期望的元素是<{}
Object>,<{} objectList>

编辑: 我只是注意到几个问题,我将ObjectList对象的XmlRootElement标记更改为@XmlRootElement(name =“
ObjectList”),将我对象的XmlRootElement标记更改为@XmlRootElement(name =“
object)。我不再得到异常,但是我现在得到并清空对象列表。

任何帮助深表感谢。

java – 使用JAXB创建不可变对象

java – 使用JAXB创建不可变对象

我正在使用JAXB从XSD文件创建 Java对象.我正在创建不可变的包装器来隐藏JAXB生成的对象(之前我正在更新JAXB对象来实现不可变接口并返回到客户端,但是意识到改变自动生成的类是不好的,因此使用包装器)

目前,我将这些不可变换的包装器归还给客户端应用程序.是否有任何选项,以便自动生成的类将是不可变的,它将避免创建不可变的包装器的额外工作.鼓励任何其他方法.

>谢谢

解决方法

您可以在将bean返回给客户端之前为您创建一个代理服务器.您将需要 javassist从类创建代理(直接从Java SE创建来自接口的代理).

然后,如果调用以“set”开头的方法,则可以抛出异常.

这是一个可重用的类,可以包装“任何”POJO的方法:

import java.lang.reflect.Method;

import javassist.util.proxy.MethodFilter;
import javassist.util.proxy.MethodHandler;
import javassist.util.proxy.Proxy;
import javassist.util.proxy.ProxyFactory;

public class Utils {

 public static <C> C createInmutableBean(Class<C> clazz,final C instance)
        throws InstantiationException,illegalaccessexception {
    if (!clazz.isAssignableFrom(instance.getClass())) {
        throw new IllegalArgumentException("given instance of class "
                + instance.getClass() + " is not a subclass of " + clazz);
    }
    ProxyFactory f = new ProxyFactory();
    f.setSuperclass(clazz);
    f.setFilter(new MethodFilter() {
        public boolean isHandled(Method m) {
            // ignore finalize()
            return !m.getName().equals("finalize");
        }
    });
    Class c = f.createClass();
    MethodHandler mi = new MethodHandler() {
        public Object invoke(Object self,Method m,Method proceed,Object[] args) throws Throwable {
            if (m.getName().startsWith("set")) {
                throw new RuntimeException("this bean is inmutable!");
            }

            return m.invoke(instance,args); // execute the original method
                                                // over the instance
        }
    };
    C proxy = (C) c.newInstance();

    ((Proxy) proxy).setHandler(mi);
    return (C) proxy;
 }
}

这里是一个示例代码.让员工成为你的豆子:

public class Employee{
  private String name="John";
  private String surname="Smith";
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public String getSurname() {
    return surname;
  }
  public void setSurname(String surname) {
    this.surname = surname;
  }
};

这里有一个测试用例,表明您可以为POJO创建一个代理,使用它的getter,但是不能使用它的setter

@Test
public void testProxy() throws InstantiationException,illegalaccessexception{
    Employee aBean = new Employee();

    //I can modify the bean
    aBean.setName("Obi-Wan");
    aBean.setSurname("Kenobi");

    //create the protected java bean with the generic utility
    Employee protectedBean = Utils.createInmutableBean(Employee.class,aBean);

    //I can read
    System.out.println("Name: "+protectedBean.getName());
    System.out.println("Name: "+protectedBean.getSurname());

    //but I can't modify
    try{
        protectedBean.setName("Luke");
        protectedBean.setSurname("Skywalker");
        throw new RuntimeException("The test should not have reached this line!");
    }catch(Exception e){
        //I should be here
        System.out.println("The exception was expected! The bean should not be modified (exception message: "+e.getMessage()+")");
        assertEquals("Obi-Wan",protectedBean.getName());
        assertEquals("Kenobi",protectedBean.getSurname());
    }
}

java – 使用JAXB处理丢失的节点

java – 使用JAXB处理丢失的节点

我目前正在使用JAXB来解析xml文件.我通过xsd文件生成了所需的类.但是,我收到的xml文件不包含生成的类中声明的所有节点.以下是我的xml文件结构的示例:
<root>
<firstChild>12/12/2012</firstChild> 
<secondChild>
<firstGrandChild>
<Id>
  </name>
  <characteristics>Description</characteristics> 
  <code>12345</code>
</Id>
</firstGrandChild>
</secondChild>
</root>

我面临以下两种情况:

>节点< name>存在于生成的类中但不存在于XML文件中
>节点没有值

在这两种情况下,该值都设置为null.我希望能够区分XML文件中何时不存在该节点以及何时存在但具有空值的节点.尽管我的搜索,我还没有想出办法.任何帮助都非常受欢迎

非常感谢您的时间和帮助

问候

解决方法

JAXB (JSR-222)实现不会为缺少的节点调用set方法.您可以在set方法中放置逻辑来跟踪它是否已被调用.
public class Foo {

    private String bar;
    private boolean barSet = false;

    public String getBar() {
       return bar;
    }

    public void setBar(String bar) {
        this.bar = bar;
        this.barSet = true;
    }

}

UPDATE

JAXB还将空节点视为具有空String的值.

Java模型

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Root {

    private String foo;
    private String bar;

    public String getFoo() {
        return foo;
    }

    public void setFoo(String foo) {
        this.foo = foo;
    }

    public String getBar() {
        return bar;
    }

    public void setBar(String bar) {
        this.bar = bar;
    }

}

演示

import java.io.File;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Root.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/forum15839276/input.xml");
        Root root = (Root) unmarshaller.unmarshal(xml);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,true);
        marshaller.marshal(root,System.out);
    }

}

input.xml中/输出

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
    <foo></foo>
</root>

关于java – 使用JAXB根据属性创建引用对象java 根据类型创建对象的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于Java / JAXB:将XML属性解组为特定的Java对象属性、Java Unmarshal使用JAXB的对象列表、java – 使用JAXB创建不可变对象、java – 使用JAXB处理丢失的节点等相关内容,可以在本站寻找。

本文标签: