Why are subordinated beans always instantiated?
Brought to you by:
aruckerjones,
sconway
Hi, just reading the documentation (https://opencsv.sourceforge.net/#recursion_into_subordinate_beans) saw this:
opencsv will instantiate the entire hierarchy of subordinate beans while reading data in, even if it does not need a subordinate bean for a particular dataset because all associated input fields are empty
Why is that? Is there a way to overcome this? Because I want subordinate beans to be null when all their binded fields are null...
The reason this happens is that we separate the creation of the bean and its subornates from the actual sets. This way we don't have to worry at each field if everything has been created we just have to worry about setting one field.
For your particular instance if a single field is being mapped to an entire object then my suggestion would be to create your own MappingStrategy - or extend whatever MappingStrategy you are using and override the setFieldValue from the AbstractMappingStrategy to allow the field to be nulled out.
Well, that seems a good approach. However I'm trying to null out the property whenever
value == null
and I don't know how to do that...Oh good catch I was focused on the setFieldValue inside and not the beanField check. Honestly if you have null then it should be null so the question is do you have a null to begin with?
If you look at the javadocs you willsee the CsvToBeanBuilder has a withFieldAsNull to help opencsv determine what should be used as a null https://opencsv.sourceforge.net/apidocs/com/opencsv/bean/CsvToBeanBuilder.html#withFieldAsNull-com.opencsv.enums.CSVReaderNullFieldIndicator- Are you setting it?
You can see an example in the CsvToBeanTest.
Yeah, I set that field to
EMPTY_SEPARATORS
. But it only nulls out the field annotated with@CsvBind...
not the entire subordinate bean, using documentation language :)To clarify the situation:
This returns
A
withb != null
, butstring == null
. The behaviour I expected (and I think it makes more sense somehow) is anA
object withb == null
Last edit: Diego 2022-11-26
Scott's been doing a great job of helping you so far, but I wanted to add a little something about the reasoning for doing it the way we did it.
It's essentially for the same reason we return an empty bean for an empty line. The line is there, just without data. The bean is nothing more than a vessel. If you want to know about the data, you will have to check the bean fields. Similar to the way some programmers treat getters that return a List: if the field is null, an empty List is created for the field and returned because the getter promises to return a List.
I completely understand it, it's just in my specific case I need to null out the object, so I'll need to perform additional operations which could be avoided if the behaviour was like I explained... no worries! This is such a nice tool anyway
AHHHH okay - I see a little better what is going on. I thought you were trying to annotate/populate an entire class (like in our tests where we do a Joda DateTime object).
No for what you are doing there is no direct solution. In cases like this I suggest you create what I call a DTO - DataTransferObject (I think technically Factory is correct but an old coworker called it DTO and the name stuck with me) to populate all the values and then create the real objects for you.
So in your case you would have something like this:
And personally I would just have an single DTO that matches your csv file and use the createObject to create the entire structure. I would only do multiple nexted DTOs if there was some complex business logic/validation/transformation you wanted to perform when create the objects.
Well, that is a good idea. I'll take it into account. Thanks!