Converters underpin everything XStream does, every time a field is marshalled/unmarshalled, it's done by a converter. Without converters, XStream simply wouldn't work.
With that out of the way, what I suspect this question is about is: why or when someone should write their own custom converter?
And the answer is: when you want a specific output that the built-in converters can't produce. If you don't care about the output format (you know it will always be marshalled/unmarshalled with XStream, won't be stored or edited by anyone else), there is almost certainly no need for custom converters. Most classes are well-covered by built-in converters.
If however you need the output to match a pre-defined format, you may find a situation where the built-in mechanisms just won't do, no matter how you tweak things with aliases, implicit collections and the like.
At this point you of course may decide to just write some custom getter/setters in the class itself, as you described, but:
- What if you need two or more different serialisation formats for a class? Granted, this happens very rarely, but would you want to burden your class with specialised code for every output format?
- It doesn't always work. Particularly if the XML/JSON format is already defined elsewhere, you may not find a combination of tricky getter/setters that will parse/output that exact format.
- But even when they work, and even if there's just one target format, what happens is that you mix some of the conversion code into the class itself.
It is considered good practice for classes to have clear responsibilities (preferably only one per class), and by putting conversion logic in the class you're abandoning that practice.
Sometimes you really have no other reasonable option (if you've got transient
fields for example, the standard way of initialising them after unmarshalling is through a readResolve()
method in the class), but XStream converters give you a way of separating that concern from what the class really does.