6

I am writing a deserialization method that converts xml to a Java object. I would like to do this dynamically and avoid writing hard coded references to specific types.

For example this is a simplified version of one of my classes.

public class MyObject { 
   public ArrayList<SubObject> SubObjects = new ArrayList<SubObject>();
}

Here is a stripped down version of the method:

public class Serializer {    
    public static <T> T fromXml(String xml, Class<T> c) {
       T obj = c.newInstance();       
       Field field = obj.getClass().getField("SubObjects");    
       //help : create instance of ArrayList<SubObject> and add an item
       //help#2 : field.set(obj, newArrayList);

       return obj;
    }
}

Calling this method would look like this:

MyObject obj = Serializer.fromXml("myxmldata", MyObject.class);

Forgive me if this is a trivial problem as I am a C# developer learning Java.

Thanks!

2
  • Can you provide an example of the XML file too? Commented Jul 7, 2009 at 16:48
  • What if subObjects is declared as an interface (such as a List)? Commented Jul 7, 2009 at 19:29

4 Answers 4

10

Should be something pretty close to:

Object list = field.getType().newInstance();

Method add = List.class.getDeclaredMethod("add",Object.class);

add.invoke(list, addToAddToList);

Hope this helps.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks, this is what I was looking for. Can you also explain how I could get the type information for SubObject in the list instance?
That's the bit that isn't present, generic type information for collections is not available at runtime in Java. Generics are implemented in the compiler.
I guess the bit you are after is how to know what class to instantiate to add to you new list object? That information just isn't available, you could add it your self by creating an annotation and annotating the SubObjects field with it, something like @SerialisationType(SubObject.class)
I found it. If you call ((ParameterizedType)field.getGenericType()).toString() you can see the full name of the type which includes SubObject. I then parsed out the class name and created a new instance through Class.forName("SubObject").newInstance(). Very hacky, but it works.
3

It seems like the real issue here is going from XML to java objects. If that is the case (and since you are new to Java), a better solution than rolling your own may be to investigate existing technologies such as:

Comments

0

In java generics are just syntax sugar and they do not exist in runtime. This is why you cannot programmatically create generic objects in runtime. Try to create non generic list and cast (however I am not sure as my experience is limited with GWT).

2 Comments

That's not quite true. If you have a class MyArray which extends ArrayList<Integer>, then you do have the type info at runtime. Also, it is possibly to instantiate an object at runtime which the code casts to a "parameterized object" - the cast will be meaningless though and your compiler will generate a type checked warning
@Oxbow: A Class will store the parameterized type of its method signatures at runtimes. An individual collection does not I believe.
0

You'll have to create a raw typed List (i.e. with no type parameters).

List subs = deserialize( ... );

If you were to set the raw typed List on your class directly:

obj.setSubObjects(subs); //You'll get an "unchecked cast" warning at compile time

Although the compiler will emit a warning, it is legal Java code and will run just fine at runtime because the parameter-type information is lost (i.e. at runtime, there is no difference between a List and a List<SomeClass>). You can of course set it reflectively also.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.