Question

Using XStream 1.4.4.

I have the following XML:

<app name="MyApp">
    <properties>
        <property name="fizz" value="buzz" />
        <property name="foo" value="bar" />
    </properties>

    <fruit type="apple" />

    <!-- ...etc. -->
</app>

And respective POJOs for the list of properties, as well as the properties themselves:

@XStreamAlias("properties")
public class Properties {
    private List<Property> properties = new ArrayList<Property>();

    public List<Property> getProperties() {
        return properties;
    }

    public void setProperties(List<Property> properties) {
        this.properties = properties;
    }
}

@XStreamAlias("property")
public class Property {
    private String name = null;

    private String value = null;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

When I try running the following code:

XStream xs = new XStream();
Strnig xml = getXML(); // Fetches the string of XML from above
App app = (App)xs.fromXML(xml);

I get:

Exception in thread "main" com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter$UnknownFieldException: No such field com.me.myapp.Properties.property
---- Debugging information ----
field               : property
class               : com.me.myapp.Properties
required-type       : com.me.myapp.Properties
converter-type      : com.thoughtworks.xstream.converters.reflection.ReflectionConverter
path                : /app/properties/property
line number         : 4
class[1]            : com.me.myapp.App
version             : null
-------------------------------
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.determineType(AbstractReflectionConverter.java:453)
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:294)
    ...rest of stack trace omitted for brevity

Where am I going wrong?

Was it helpful?

Solution

You don't need annotations at all. Just use alias Property.class as "properties" and XStream will take care of everything else for you.

OTHER TIPS

Delete Properties class altogether. Remove XStream aliases from Property class. Add Property class directly to App class. Uses the following aliases to get XStream serializing/deserializing the way you want it to:

xstream.alias("property", Property.class);
xstream.aliasField("property", Property.class, "properties");

That should do it :-)

Problem

  • You have a class com.me.myapp.Properties, aliased to properties
  • Within it, you have an instance variable called properties
  • That's two levels of properties
  • Your XML has one level of properties

My Suggestion

  • Put an annotation just above the declaration:

    @XStreamImplicit(itemFieldName="property")
    private List<Property> properties = new ArrayList<Property>()
    
  • This says to omit the element <properties> wrapping the List (implicit list), and also to use the element <property> for each item within the list.

Testing:

  • Once you think you have the correct setup, firstly test by generating XML:

    XStream xs = new XStream();
    App app = ...;              // Construct & populate a new App object
    String xml = xs.toXML(app); // Convert to XML
    System.out.println(xml);
    // This shows the XML format that must be used to parse XML to App.
    

This code is converting XML (given by you) to App object. As your given code was insufficient so I am pasting this whole code here. I think you forget to mention xstream.processAnnotations(App.class);

<app name="MyApp">
    <properties>
        <property name="fizz" value="buzz" />
        <property name="foo" value="bar" />
    </properties>
</app>

Classes

package com.xstream;

import com.thoughtworks.xstream.annotations.XStreamAlias;

@XStreamAlias("app")
public class App {

  @XStreamAlias("properties")
  private Properties properties;

  /**
   * @param properties
   */
  public App(Properties properties) {
    super();
    this.properties = properties;
  }

  /**
   * 
   */
  public App() {
    super();
    // TODO Auto-generated constructor stub
  }

  /**
   * @return the properties
   */
  public Properties getProperties() {
    return properties;
  }

  /**
   * @param properties the properties to set
   */
  public void setProperties(Properties properties) {
    this.properties = properties;
  }

  /* (non-Javadoc)
   * @see java.lang.Object#toString()
   */
  @Override
  public String toString() {
    return "App [properties=" + properties + "]";
  }

}


----------

package com.xstream;                                                                                                   

import java.util.ArrayList;                                                                                            
import java.util.List;                                                                                                 

import com.thoughtworks.xstream.annotations.XStreamAlias;                                                              
import com.thoughtworks.xstream.annotations.XStreamImplicit;                                                           

@XStreamAlias("properties")                                                                                            
public class Properties {                                                                                              

    @XStreamImplicit(itemFieldName = "property")                                                                       
    private List<Property> property = new ArrayList<Property>();                                                       

    public List<Property> getProperties() {                                                                            
        return property;                                                                                               
    }                                                                                                                  

    public void setProperties(List<Property> properties) {                                                             
        this.property = properties;                                                                                    
    }                                                                                                                  

    /**                                                                                                                
     * @return the property                                                                                            
     */                                                                                                                
    public List<Property> getProperty() {                                                                              
      return property;                                                                                                 
    }                                                                                                                  

    /**                                                                                                                
     * @param property the property to set                                                                             
     */                                                                                                                
    public void setProperty(List<Property> property) {                                                                 
      this.property = property;                                                                                        
    }                                                                                                                  

    /* (non-Javadoc)                                                                                                   
     * @see java.lang.Object#toString()                                                                                
     */                                                                                                                
    @Override                                                                                                          
    public String toString() {                                                                                         
      return "Properties [property=" + property + "]";                                                                 
    }                                                                                                                  


}                                                                                                                      
----------------

package com.xstream;

import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;

@XStreamAlias("property")
public class Property {

  @XStreamAsAttribute
    private String name = null;

  @XStreamAsAttribute
    private String value = null;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    /* (non-Javadoc)
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
      return "Property [name=" + name + ", value=" + value + "]";
    }


}

Code for Main class is.

XStream xstream = new XStream();
xstream.processAnnotations(App.class);

App app = null;
try {
  app = (App) xstream.fromXML(new FileInputStream(new File("D:/property.xml")));
}
catch (FileNotFoundException e) {
  e.printStackTrace();
}

System.out.println(app.toString());  
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top