If all your real cases are so simple as example in your question then you can use what you like (i.e. what you've already used before).
But if more complex cases exist then you should provide some kind of parser first. Even for last string in your example it's not so simple to generate necessary code:
public Object buildObject (Parser parser, Item param) {
if (!parser.hasNext ()) {
return param.getValue ();
}
Item nextItem = parser.getNextItem (); //1st call: "TestString", 2nd call: "StringReader"
if (nextItem.isParameter ()) { //1st call: true, 2nd call: false
return buildObject (parser, nextItem);
} else if (nextItem.isClassName () { //2nd call: true
Class c = Class.forName (nextItem.getStringValue ());
Constructor ctr = c.getConstructor (param.getClassName ()); //getClassName returns "String"
Object obj = ctr.newInstance (param.getValue ());
return buildObject (parser, new Item (obj));
} else {
throw new ParseException ("Illegal input");
}
}
This peace of code is still very buggy (there is no try/catch, there is no some necessary logic), but it demonstrates the basic idea (and this idea is about it's not so easy task).
Maybe it's worth to look for some 3rd party libs (even if you have to sacrifice your file format and accept their format).