[
https://issues.apache.org/jira/browse/GROOVY-12296?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Paul King updated GROOVY-12296:
-------------------------------
Description:
{{CsvBuilder.toCsv(data, type)}} derives its schema via Jackson's
{{CsvMapper.schemaFor(type)}}, which emits columns in Jackson's introspected
property order — alphabetical — rather than declaration order:
{code:groovy}
record Person(String name, int age, String city) {}
def people = [new Person('Alice', 30, 'Perth')]
println groovy.csv.CsvBuilder.toCsv(people, Person)
{code}
produces:
{noformat}
age,city,name
30,Perth,Alice
{noformat}
The same applies to plain classes, not just records. Note that the map-based
{{toCsv(Collection<Map>)}} overload behaves differently — it respects the
insertion order of the first map's keys.
This is not documented: the "Typed writing" section of the user guide and the
{{toCsv(data, type)}} javadoc say nothing about column order. The doc/test
example ({{Product}} with fields {{name}}, {{price}}) is coincidentally already
alphabetical, so the current tests pass regardless of ordering behavior.
*Workaround (verified):* annotate the type with {{@JsonPropertyOrder}}:
{code:groovy}
@JsonPropertyOrder(['name', 'age', 'city'])
record Person(String name, int age, String city) {}
{code}
produces {{name,age,city}} as expected.
*Possible resolutions:*
# For records, build the schema from {{type.getRecordComponents()}}
(declaration order) when no {{@JsonPropertyOrder}} is present.
# Document the current behavior and the {{@JsonPropertyOrder}} workaround in
the "Typed writing" section of the user guide, using an example whose fields
are not already in alphabetical order so the behavior is actually exercised by
the doc tests.
Since the module is still {{@Incubating}}, option 1 can be adopted without
compatibility concerns.
> CsvBuilder: toCsv(data, type) emits columns in alphabetical rather than
> declaration order
> -----------------------------------------------------------------------------------------
>
> Key: GROOVY-12296
> URL: https://issues.apache.org/jira/browse/GROOVY-12296
> Project: Groovy
> Issue Type: Bug
> Reporter: Paul King
> Priority: Major
>
> {{CsvBuilder.toCsv(data, type)}} derives its schema via Jackson's
> {{CsvMapper.schemaFor(type)}}, which emits columns in Jackson's introspected
> property order — alphabetical — rather than declaration order:
> {code:groovy}
> record Person(String name, int age, String city) {}
> def people = [new Person('Alice', 30, 'Perth')]
> println groovy.csv.CsvBuilder.toCsv(people, Person)
> {code}
> produces:
> {noformat}
> age,city,name
> 30,Perth,Alice
> {noformat}
> The same applies to plain classes, not just records. Note that the map-based
> {{toCsv(Collection<Map>)}} overload behaves differently — it respects the
> insertion order of the first map's keys.
> This is not documented: the "Typed writing" section of the user guide and the
> {{toCsv(data, type)}} javadoc say nothing about column order. The doc/test
> example ({{Product}} with fields {{name}}, {{price}}) is coincidentally
> already alphabetical, so the current tests pass regardless of ordering
> behavior.
> *Workaround (verified):* annotate the type with {{@JsonPropertyOrder}}:
> {code:groovy}
> @JsonPropertyOrder(['name', 'age', 'city'])
> record Person(String name, int age, String city) {}
> {code}
> produces {{name,age,city}} as expected.
> *Possible resolutions:*
> # For records, build the schema from {{type.getRecordComponents()}}
> (declaration order) when no {{@JsonPropertyOrder}} is present.
> # Document the current behavior and the {{@JsonPropertyOrder}} workaround in
> the "Typed writing" section of the user guide, using an example whose fields
> are not already in alphabetical order so the behavior is actually exercised
> by the doc tests.
> Since the module is still {{@Incubating}}, option 1 can be adopted without
> compatibility concerns.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)