Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

datatable: Automatic list conversion #408

Merged
merged 7 commits into from
Jun 13, 2018

Conversation

aslakhellesoy
Copy link
Contributor

Summary

Provide a simple (one-liner) to convert a data table to a list of objects:

registry.defineDataTableType(DataTableType.entry(Author.class))

Also provide a simple (one-liner) to convert a cell into a "string wrapper" value object:

registry.defineDataTableType(DataTableType.cell(AirportCode.class))

Details

  • entry uses Jackson Databind's ObjectMapper to convert a table entry (Map<String,String>) into an object.
  • cell uses reflection to call a String constructor.

Motivation and Context

Cucumber-JVM 2 used to convert tables to List<Something> automatically, with zero configuration. Version 3 removed XStream and added a more flexible conversion API, but some users have reported this as a regression (in ease of use). They now need to write more code to do something that used to be automatic.

This PR makes it easy again, while keeping the flexible API.

Types of changes

  • Bug fix (non-breaking change which fixes an issue).
  • New feature (non-breaking change which adds functionality).
  • Breaking change (fix or feature that would cause existing functionality to not work as expected).

Checklist:

  • I've added tests for my code.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.

@aslakhellesoy
Copy link
Contributor Author

This is a proposed fix for cucumber/cucumber-jvm#1388

Copy link
Contributor

@mpkorstanje mpkorstanje left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the general idea. This is really concise!

Some thoughts:

We're currently using Jackson internally. Using it this way exposes Jackson (by the way of implied constructors, annotations, ect). This may lead to conflicts between our internal version and the one that is used externally.

I am not 100% confident our shaded jackson version will handle non-shaded annotations from the same version properly.

So I think it might be better to provided this as a plugin module instead that depends on a provided version of Jackson.

It's a trade of between the convenience of not having to add two extra dependencies and mind boggling bugs.

@Override
public T transform(String cell) {
try {
return constructor.newInstance(cell);
Copy link
Contributor

@mpkorstanje mpkorstanje Jun 12, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To the best of my knowledge objectMapper.convertValue("someThing", SingleArgConstructor.class); works. So you use Jackson here as well. I believe it is also a bit more flexible as it will check for methods named fromString as well if there is no constructor.

It simplifies the documentation (refer to Jackons)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the pointer - will update accordingly

@aslakhellesoy
Copy link
Contributor Author

I am not 100% confident our shaded jackson version will handle non-shaded annotations from the same version properly.

I think that's fine. People don't have to use those annotations. Classes with setters and public fields work fine without annotations. If people need to use annotations, they can write their own transformer, using an unshaded Jackson or something else.


// Defines a DataTableType that converts a single cell
// to an object, by calling its `String` constructor (if it exists).
registry.defineDataTableType(DataTableType#cell(Class))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add an implementation note here: Something along the lines of we're using Jackson, but don't rely on anything but getters/setter/constructor/fromString/valueOf methods?

@mpkorstanje
Copy link
Contributor

People don't have to use those annotations.

They will. And someone will blog about this amazing thing they discovered too. :D

Let's at least warn them.

*
* @param type the type of the cell
* @param <T> see <code>type</code>
* @throws CucumberDataTableException if <code>type</code> does not has a public String constructor.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not thrown anymore. If only we could test documentation. ;)

@aslakhellesoy aslakhellesoy merged commit fc14437 into master Jun 13, 2018
aslakhellesoy added a commit that referenced this pull request Jun 13, 2018
@luke-hill luke-hill deleted the datatable-automatic-list-conversion branch March 20, 2019 09:44
@lock
Copy link

lock bot commented Mar 21, 2020

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@lock lock bot locked as resolved and limited conversation to collaborators Mar 21, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants