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-java: Empty cell are not converted to null's for String class #1617

Closed
gkalnytskyi opened this issue Apr 24, 2019 · 9 comments · Fixed by #1722
Closed

datatable-java: Empty cell are not converted to null's for String class #1617

gkalnytskyi opened this issue Apr 24, 2019 · 9 comments · Fixed by #1722
Assignees
Milestone

Comments

@gkalnytskyi
Copy link

Summary

The empty cell is not converted to (Double)null in Cucumber 4.3.0, as it happened in Cucumber 1.2.5

In Cucumber 1.2.5 empty cell was converted to null of type Double, when performing asMap(String,Double) table conversion. This no longer happens in Cucumber 4.3.0. I also couldn't find the way to override this behavior because just adding new DataTableType definition results in io.cucumber.datatable.DublicateTypeException.

typeRegistry.defineDataTableType(
    new DataTableType(
        Double.class,
        (TableCellTransformer<Double>) value ->
            (!value.isEmpty()) ? (Double.parseDouble(value)) : (null)));

Expected Behavior

Empty cell is converted to null by default for nullable number types (Double, Float, Int etc.). So that the table in the following step

Then the marker values are
  | M1   | 1.7988 |
  | M2   |        |
  | M3   | 1.5312 |
  | M4   | 1.7720 |
  | M5   | 1.6840 |
  | M6   | 0.0000 |
  | M9   |        |
  | M12 | 1.7002 |

is transformed to

{
    "M1": 1.7988,
    "M2": null,
    "M3": 1.5312,
    "M4": 1.7720,
    "M5": 1.6840,
    "M6": 0.0,
    "M9": null,
    "M12": 1.7002,
}

Current Behavior

Exception is thrown:
io.cucumber.datatable.CucumberDataTableException: 'java.util.List<java.util.List<java.lang.Double>>' could not transform

Possible Solution

Convert empty cells to null values, or allow to override default build-in type transformations.

Steps to Reproduce (for bugs)

  1. The table in the following step:

    Then the marker values are

    | M1 | 1.7988 |
    | M2 | |
    | M3 | 1.5312 |
    | M4 | 1.7720 |
    | M5 | 1.6840 |
    | M6 | 0.0000 |
    | M9 | |
    | M12 | 1.7002 |

  2. Is trasformed to a Map

    @then("Then the marker values are")
    public void theMarkerValuesAre(DataTable expectedValues) {
    Map<String, Double> expected = expectedValues.asMap(String.class, Double.class);
    }

  3. CucumberDataTableException is thrown with message: 'java.util.List<java.util.List<java.lang.Double>>' could not transform

Context & Motivation

It could be useful to represent the clearing of the input value in the form where user can enter/update several similar values in one go.

Your Environment

  • Version used: 4.3.0
  • Operating System and version: Windows 10
  • Link to your project: N/A
@mpkorstanje mpkorstanje transferred this issue from cucumber/common Apr 29, 2019
@mpkorstanje
Copy link
Contributor

mpkorstanje commented Apr 29, 2019

This should be fixed with a PR against cucumber/datatable.

To remain consistent the empty string should always be converted to null (so also for strings) and doing this would be a breaking change. Meaning this would have to be picked up with v5.

@mpkorstanje mpkorstanje added this to the 5.0.0 milestone Apr 29, 2019
@mpkorstanje
Copy link
Contributor

For the the time being fixing this for all types but String would be good too.

@gkalnytskyi
Copy link
Author

@mpkorstanje , sorry for asking, but where I can find some information about how to build datatable project in monorepo?
At the moment when I try to build the datatable-parent project I receive several errors of the following type: package io.cucumber.datatable.dependency.com.fasterxml.jackson.databind does not exist

@mpkorstanje
Copy link
Contributor

Try running mvn clean install first. The dependency module is shading in some jars. IDEA doesn't pick that up automatically.

@gkalnytskyi
Copy link
Author

Thanks! That was easy.

@mpkorstanje mpkorstanje added Bug good first issue Good for newcomers 🙏 help wanted Help wanted - not prioritized by core team labels May 18, 2019
glibas pushed a commit to glibas/cucumber that referenced this issue Jun 7, 2019
@glibas glibas self-assigned this Jun 7, 2019
@mpkorstanje mpkorstanje reopened this Jun 7, 2019
@mpkorstanje
Copy link
Contributor

Data table version still needs to be updated.

@mpkorstanje
Copy link
Contributor

And then we have to wait for 5.0.0 to make the empty String convert to null.

@mpkorstanje mpkorstanje reopened this Jun 7, 2019
@mpkorstanje mpkorstanje reopened this Jun 14, 2019
@mpkorstanje mpkorstanje modified the milestones: 4.x.x, 5.0.0 Jun 15, 2019
@mpkorstanje mpkorstanje removed good first issue Good for newcomers 🙏 help wanted Help wanted - not prioritized by core team labels Jun 15, 2019
@mpkorstanje mpkorstanje changed the title datatable-java: Empty cell are not converted to null's for Double class datatable-java: Empty cell are not converted to null's for String class Jun 15, 2019
@hsynkrtl
Copy link

hsynkrtl commented Nov 4, 2019

how can i now pass an empty string to a datatable.

  | street | houseNumber | city         | zip | country | state | type            |
  |      |           | Trololotown2 |     | AZ           | WY    | ADDRESS |

with the last update of datatable street and housNumber get [null] instead of an empty string "" which is valid for a string value to be empty.

@mpkorstanje
Copy link
Contributor

@hsynkrtl you're replying to a closed issue which means that chances of anybody reading this are absolutely terrible. I happened to see this by sheer chance.

I would suggest that you make empty strings explicit by using the text [empty] and then prior to converting the entry to an object replace the "[empty]" strings with "".

mpkorstanje added a commit that referenced this issue Jan 9, 2020
Empty data table cells can either be considered null or empty strings.
For example table below can converted to a map as
`{name=Aspiring Author, first publication=}` or
`{name=Aspiring Author, first publication=null}`.

```gherkin
 | name            | first publication |
 | Aspiring Author |                   |
```

And as demonstrated #1617 there are good reasons to default the empty
table cell to null. However this does not cover all cases. There are
however good use cases to use the empty string.

By declaring a table transformer with a replacement string it becomes
possible to explicitly disambiguate between the two scenarios. For
example:

```gherkin
Given some authors
   | name            | first publication |
   | Aspiring Author |                   |
   | Ancient Author  | [blank]           |
```

```java
@DataTableType(replaceWithEmptyString = "[blank]")
public Author convert(Map<String, String> entry){
  return new Author(
     entry.get("name"),
     entry.get("first publication")
  );
}

@given("some authors")
public void given_some_authors(List<Author> authors){
  // authors = [Author(name="Aspiring Author", firstPublication=), Author(name="Ancient Author", firstPublication=null)]
}
```
mpkorstanje added a commit that referenced this issue Jan 9, 2020
Empty data table cells can either be considered null or empty strings.
For example table below can converted to a map as
`{name=Aspiring Author, first publication=}` or
`{name=Aspiring Author, first publication=null}`.

```gherkin
 | name            | first publication |
 | Aspiring Author |                   |
```

And as demonstrated #1617 there are good reasons to default the empty
table cell to null. However this does not cover all cases. There are
however good use cases to use the empty string.

By declaring a table transformer with a replacement string it becomes
possible to explicitly disambiguate between the two scenarios. For
example:

```gherkin
Given some authors
   | name            | first publication |
   | Aspiring Author |                   |
   | Ancient Author  | [blank]           |
```

```java
@DataTableType(replaceWithEmptyString = "[blank]")
public Author convert(Map<String, String> entry){
  return new Author(
     entry.get("name"),
     entry.get("first publication")
  );
}

@given("some authors")
public void given_some_authors(List<Author> authors){
  // authors = [Author(name="Aspiring Author", firstPublication=null), Author(name="Ancient Author", firstPublication=)]
}
```
mpkorstanje added a commit that referenced this issue Jan 10, 2020
Empty data table cells can either be considered null or empty strings.
For example table below can converted to a map as
`{name=Aspiring Author, first publication=}` or
`{name=Aspiring Author, first publication=null}`.

```gherkin
 | name            | first publication |
 | Aspiring Author |                   |
```

And as demonstrated #1617 there are good reasons to default the empty
table cell to null. However this does not cover all cases. There are
however good use cases to use the empty string.

By declaring a table transformer with a replacement string it becomes
possible to explicitly disambiguate between the two scenarios. For
example:

```gherkin
Given some authors
   | name            | first publication |
   | Aspiring Author |                   |
   | Ancient Author  | [blank]           |
```

```java
@DataTableType(replaceWithEmptyString = "[blank]")
public Author convert(Map<String, String> entry){
  return new Author(
     entry.get("name"),
     entry.get("first publication")
  );
}

@given("some authors")
public void given_some_authors(List<Author> authors){
  // authors = [Author(name="Aspiring Author", firstPublication=null), Author(name="Ancient Author", firstPublication=)]
}
```
mpkorstanje added a commit that referenced this issue Jan 10, 2020
Empty data table cells can either be considered null or empty strings.
For example table below can converted to a map as
`{name=Aspiring Author, first publication=}` or
`{name=Aspiring Author, first publication=null}`.

```gherkin
 | name            | first publication |
 | Aspiring Author |                   |
```

And as demonstrated #1617 there are good reasons to default the empty
table cell to null. However this does not cover all cases. There are
however good use cases to use the empty string.

By declaring a table transformer with a replacement string it becomes
possible to explicitly disambiguate between the two scenarios. For
example:

```gherkin
Given some authors
   | name            | first publication |
   | Aspiring Author |                   |
   | Ancient Author  | [blank]           |
```

```java
@DataTableType(replaceWithEmptyString = "[blank]")
public Author convert(Map<String, String> entry){
  return new Author(
     entry.get("name"),
     entry.get("first publication")
  );
}

@given("some authors")
public void given_some_authors(List<Author> authors){
  // authors = [Author(name="Aspiring Author", firstPublication=null), Author(name="Ancient Author", firstPublication=)]
}
```
mpkorstanje added a commit that referenced this issue Jan 10, 2020
Empty data table cells can either be considered null or empty strings.
For example table below can converted to a map as
`{name=Aspiring Author, first publication=}` or
`{name=Aspiring Author, first publication=null}`.

```gherkin
 | name            | first publication |
 | Aspiring Author |                   |
```

And as demonstrated #1617 there are good reasons to default the empty
table cell to null. However this does not cover all cases. There are
however good use cases to use the empty string.

By declaring a table transformer with a replacement string it becomes
possible to explicitly disambiguate between the two scenarios. For
example:

```gherkin
Given some authors
   | name            | first publication |
   | Aspiring Author |                   |
   | Ancient Author  | [blank]           |
```

```java
@DataTableType(replaceWithEmptyString = "[blank]")
public Author convert(Map<String, String> entry){
  return new Author(
     entry.get("name"),
     entry.get("first publication")
  );
}

@given("some authors")
public void given_some_authors(List<Author> authors){
  // authors = [Author(name="Aspiring Author", firstPublication=null), Author(name="Ancient Author", firstPublication=)]
}
```
mpkorstanje added a commit that referenced this issue Jan 10, 2020
Empty data table cells can either be considered null or empty strings.
For example table below can converted to a map as
`{name=Aspiring Author, first publication=}` or
`{name=Aspiring Author, first publication=null}`.

```gherkin
 | name            | first publication |
 | Aspiring Author |                   |
```

And as demonstrated #1617 there are good reasons to default the empty
table cell to null. However this does not cover all cases. There are
however good use cases to use the empty string.

By declaring a table transformer with a replacement string it becomes
possible to explicitly disambiguate between the two scenarios. For
example:

```gherkin
Given some authors
   | name            | first publication |
   | Aspiring Author |                   |
   | Ancient Author  | [blank]           |
```

```java
@DataTableType(replaceWithEmptyString = "[blank]")
public Author convert(Map<String, String> entry){
  return new Author(
     entry.get("name"),
     entry.get("first publication")
  );
}

@given("some authors")
public void given_some_authors(List<Author> authors){
  // authors = [Author(name="Aspiring Author", firstPublication=null), Author(name="Ancient Author", firstPublication=)]
}
```
mpkorstanje added a commit that referenced this issue Jan 10, 2020
Empty data table cells can either be considered null or empty strings.
For example table below can converted to a map as
`{name=Aspiring Author, first publication=}` or
`{name=Aspiring Author, first publication=null}`.

```gherkin
 | name            | first publication |
 | Aspiring Author |                   |
```

And as demonstrated #1617 there are good reasons to default the empty
table cell to null. However this does not cover all cases. There are
however good use cases to use the empty string.

By declaring a table transformer with a replacement string it becomes
possible to explicitly disambiguate between the two scenarios. For
example:

```gherkin
Given some authors
   | name            | first publication |
   | Aspiring Author |                   |
   | Ancient Author  | [blank]           |
```

```java
@DataTableType(replaceWithEmptyString = "[blank]")
public Author convert(Map<String, String> entry){
  return new Author(
     entry.get("name"),
     entry.get("first publication")
  );
}

@given("some authors")
public void given_some_authors(List<Author> authors){
  // authors = [Author(name="Aspiring Author", firstPublication=null), Author(name="Ancient Author", firstPublication=)]
}
```
mpkorstanje added a commit that referenced this issue Jan 10, 2020
Empty data table cells can either be considered null or empty strings.
For example table below can converted to a map as
`{name=Aspiring Author, first publication=}` or
`{name=Aspiring Author, first publication=null}`.

```gherkin
 | name            | first publication |
 | Aspiring Author |                   |
```

And as demonstrated #1617 there are good reasons to default the empty
table cell to null. However this does not cover all cases. There are
however good use cases to use the empty string.

By declaring a table transformer with a replacement string it becomes
possible to explicitly disambiguate between the two scenarios. For
example:

```gherkin
Given some authors
   | name            | first publication |
   | Aspiring Author |                   |
   | Ancient Author  | [blank]           |
```

```java
@DataTableType(replaceWithEmptyString = "[blank]")
public Author convert(Map<String, String> entry){
  return new Author(
     entry.get("name"),
     entry.get("first publication")
  );
}

@given("some authors")
public void given_some_authors(List<Author> authors){
  // authors = [Author(name="Aspiring Author", firstPublication=null), Author(name="Ancient Author", firstPublication=)]
}
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants