You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by "ASF GitHub Bot (Jira)" <ji...@apache.org> on 2026/08/25 22:18:00 UTC

[jira] [Commented] (GROOVY-12296) CsvBuilder: toCsv(data, type) emits columns in alphabetical rather than declaration order

    [ https://issues.apache.org/jira/browse/GROOVY-12296?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18108108#comment-18108108 ] 

ASF GitHub Bot commented on GROOVY-12296:
-----------------------------------------

paulk-asert opened a new pull request, #2832:
URL: https://github.com/apache/groovy/pull/2832

   …ical rather than declaration order




> 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)