将列表解组到JavaFX SimpleListProperty中 [英] Unmarshalling a List into a JavaFX SimpleListProperty

查看:203
本文介绍了将列表解组到JavaFX SimpleListProperty中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个嵌套的对象层次结构,如下所示:

I've got a nested object hierarchy which looks like this:

Profile:包含List<Category>

Category包含一个List<Script>.它通过JavaFX SimpleListProperty公开,因此可以通过JavaFX的数据绑定进行绑定.

Category contains a List<Script>. It is exposed via a JavaFX SimpleListProperty, so that it can be bound to via JavaFX's data binding.

Script仅包含简单值.

我只是使用JAXB编组和解编POJO.不涉及数据库或XML模式.

I'm just using JAXB to marshall and unmarshall POJOs. There are no databases or XML schemas involved.

Profile值编组可以正常工作,并生成有效的XML.但是,稍后解组相同的XML文件会导致每个Category包含一个空的List<Script>.这似乎是由于Category通过使用JavaFX可绑定属性存储List<Script>的事实.

Marshalling a Profile value works fine, and generates valid XML. However, unmarshalling the same XML file later, results in each Category containing an empty List<Script>. This appears to be due to the fact that Category stores the List<Script> by using a JavaFX bindable property.

是否有办法使JAXB正确反序列化为包含自定义对象的SimpleListProperty?

Is there a way to make JAXB properly deserialize into a SimpleListProperty that contains a custom object?

这是一个最小的示例,它演示了相同的问题.

Here's a minimal sample that demonstrates the same issue.

public class Main 
{
    public static void main(String[] args) throws Exception
    {                
        Script script1 = new Script();
        script1.name = "Script 1";
        script1.otherData = "Script 1's data";

        Script script2 = new Script();
        script2.name = "Script 2";
        script2.otherData = "Script 2's data";

        ArrayList<Script> scriptList = new ArrayList<Script>();
        scriptList.add(script1);
        scriptList.add(script2);

        Category category1 = new Category();
        category1.name = "Category 1";           
        category1.setCategoryScripts(scriptList);        

        Category category2 = new Category();
        category2.name = "Category 2";
        category2.setCategoryScripts(scriptList);        

        Profile profile = new Profile();
        profile.name = "Profile 1";
        profile.categories.add(category1);
        profile.categories.add(category2);

        JAXBContext context = JAXBContext.newInstance(Profile.class);
        Marshaller m = context.createMarshaller();
        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        StringWriter xml = new StringWriter();
        m.marshal(profile, xml);

        System.out.println(xml.toString());

        Profile deserializedProfile = (Profile)context
                .createUnmarshaller()
                .unmarshal(new StringReader(xml.toString()));                

        System.out.println("Profile: " + deserializedProfile.name);
        for(Category cat : deserializedProfile.categories)
        {
            System.out.println("Category: " + cat.name);
            System.out.println("Scripts:");
            for(Script s : cat.getCategoryScripts())
            {
                System.out.printf("\nName: %s, Data: %s", s.name, s.otherData);
            }
        }
    }
}

@XmlRootElement
class Profile
{
    @XmlElement
    String name;
    @XmlElementWrapper
    @XmlElement
    ArrayList<Category> categories = new ArrayList<Category>();
}

@XmlRootElement
class Category
{
    @XmlElement
    String name;

    ListProperty<Script> categoryScripts = new SimpleListProperty<Script>();
    @XmlElementWrapper
    @XmlElement
    public final List<Script> getCategoryScripts() { return categoryScripts.get(); }
    public final void setCategoryScripts(List<Script> value) { categoryScripts.set(FXCollections.observableArrayList(value)); }
    public ListProperty<Script> categoryScriptProperty() { return categoryScripts; }            
}

@XmlRootElement
class Script
{
    @XmlElement
    String name;
    @XmlElement
    String otherData;
}

推荐答案

我相信您会遇到JAXB的怪异之处.请注意,您没有addCategoryScript方法.那么,JAXB如何将Script对象添加到列表中?

I believe you're running into a weirdness of JAXB. Notice that you don't have an addCategoryScript method. So how is JAXB going to add Script objects to the list?

它可以创建一个自己的列表,然后用setCategoryScripts交给您,但是它怎么知道要创建哪种列表?

It could create a list of it's own, then give it to you with setCategoryScripts, but how would it know what kind of list to create?

它通过调用getCategoryScripts来获取初始(空)列表,然后向其中添加元素来解决该难题.

It solves that dilemma by calling getCategoryScripts to get the initial (empty) list, and then add elements to it.

但是,如果您返回内部列表的副本,会发生什么?
啊哈!列表完成后,呼叫setCategoryScripts.

But then what happens if you returned a copy of the internal list?
Ah Ha! Call setCategoryScripts when the list is complete.

这意味着它将用getCategoryScripts返回的列表调用setCategoryScripts.

This means that it'll call setCategoryScripts with the list returned by getCategoryScripts.

我有一个需要特殊处理的实现,所以我要做的是:

I has an implementation that needed some special handling, so what I did was:

public List<MyObj> getMyList() {
    return this.myList;
}
public void setMyList(List<MyObj> myList) {
    this.myList.clear();
    for (MyObj o : myList)
        this.myList.add(handle(o));
}

但是,哎呀.对clear的调用实际上清除了传入的objList参数,但我一无所获.

But oops. The call to clear actually cleared the incoming objList parameter, and I ended up with nothing.

我的解决方案是在继续操作之前复制参数列表.

My solution was to copy the parameter list before proceeding.

这篇关于将列表解组到JavaFX SimpleListProperty中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆