jackson-dataformats-text
jackson-dataformats-text copied to clipboard
[jackson-dataformat-csv:2.8.11/2.12.2]CsvMapper unrecognised the @JsonProperty
the result is
AppsFlyerRawDataBean.java.txt appsflyer-raw-data.csv
final CsvMapper mapper = new CsvMapper();
final CsvSchema schema = mapper.schemaFor(AppsFlyerRawDataBean.class);
final ObjectReader objectReader = mapper.readerFor(AppsFlyerRawDataBean.class).with(schema);
final Collection<AppsFlyerRawData> result = new ArrayList<>(20);
try (final Reader reader = new FileReader(csv)) {
final MappingIterator<AppsFlyerRawDataBean> records = objectReader.readValues(reader);
while (records.hasNextValue()) {
final AppsFlyerRawDataBean one = records.nextValue();
if (isBlank(one)) {
continue;
}
result.add(one);
}
}
First things, first: PLEASE DO NOT USE
@JsonIgnoreProperties(ignoreUnknown = true)
on tests. This is VERY common way to hide simple problems that you could fix if you saw them. Only use that in production once other problems are resolved (if at all).
Second: if input contains header line (which I think is the case here), your schema must indicate this:
schema = schema.withUseHeader(true);
You probably do not need create schema from POJO class either, as long as names from header line match expected property names (either from getter name, or via annotation).
With these changes you may be able to get better results and see if there are other problems.
@cowtowncoder Do not use @JsonIgnoreProperties(ignoreUnknown = true) , I think it is not correct way because csv has 90 columns and programmer just need extracts 30 columns. CSV comes from the collaboration company.
Second: schema = schema.withUseHeader(true); I had a try a few days ago with the same result.
POJO property names does not match the CSV header. You can open the two files: appsflyer-raw-data.csv
To me header line names do seem to match annotated names?
-
Campaign
on header row matches@JosonProperty("Campaign")
ofprivate String campaignName
-
Campaign ID
similarly matchescampaignId
property
At this point I would need either:
- Specific exception message of what fails? Which property/column is mismatching OR
- Full unit test to reproduce the issue
No any exception on fails. Do you need my full test-case?
A test case that shows the problem with assertions would help: the original picture simply showed a POJO with values, some of which were null
s. That does not really tell me much about what the problem is: what @JsonProperty
seems to be ignored? (which POJO property should have gotten value from CSV but didn't?).
Hello @cowtowncoder ,
I recently came across that issue because I faced the same problem within one of my projects. I created a repo containing a (hopefully meaningful) test case.
https://github.com/sbszcz/jackson-csv-java-example
Mapping the content of the columns does not work. I have no idea why. The content seems to be mapped to arbitrary pojo properties.
Could you please have a look at this?
Thank you, Sebastian
Looking at the example @sbszcz (thank you!) -- my first instinct is that I don't understand why there is no fail for non-annotated case since there is no match from header names to actual names.
@sbszcz A few issues with the code, solving of which will make things work.
First: you should not usually (need to) combine 2 types of CsvSchema
s (one generated from POJOs, using specific ordering; another read from header) -- in this case I think only latter makes sense.
Sometimes there are benefits from combining this way; but if so, you almost certainly want to use this line too:
csvSchema = csvSchema.withColumnReordering(true);
which ensures that the information is combined: otherwise explicitly specified schema (from POJO, and ordering it defines) is used.
So, instead of starting with mapper.schemaFor(Type.class)
, start with CsvSchema.emptySchema()
.
Second, since there are entries in input that do not map to POJO (at least in the test), disable DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES
.
This makes test with annotations pass.
The problem without using annotations is that there is no mapping between names from CSV file header (in German) and property names in PlainTransaction
, so that cannot pass quite as specified.
It would be possible to programmatically build CsvSchema
, and then force skipping of the first (data) row:
schema = schema.withSkipFirstDataRow(true);
Or, even specify the expected ordering for POJO Fields with @JsonPropertyOrder
: otherwise ordering used is alphabetic (JDK does not guarantee ordering for fields within class so CSV module defauilts to alphabetic ordering).
@zhaoxi2000 I think you have the same problem: your POJO definition does not specify ordering of properties with @JsonPropertyOrder
, and the default ordering is alphabetic. That would then map first 5 names into 5 columns, which is not what you want based on header line.
Instead leave out the whole schemaFor(AppsFlyerRawDataBean.class)
and instead use .withHeader()
when constructing CsvSchema
.
At this point I don't see actual bug to fix, but I want to help ensure that usage can be changed to work for the use case, so keeping issue open.