Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,17 @@ public class ApiClient {
return this;
}

/**
* <p>Set LocalDateTimeFormat.</p>
*
* @param dateFormat a {@link java.time.format.DateTimeFormatter} object
* @return a {@link {{invokerPackage}}.ApiClient} object
*/
public ApiClient setLocalDateTimeFormat(DateTimeFormatter dateFormat) {
JSON.setLocalDateTimeFormat(dateFormat);
return this;
}

{{/jsr310}}
/**
* <p>Set LenientOnJson.</p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,10 @@ import java.text.ParseException;
import java.text.ParsePosition;
{{#jsr310}}
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
{{/jsr310}}
import java.util.Date;
import java.util.Locale;
Expand All @@ -59,6 +61,7 @@ public class JSON {
{{#jsr310}}
private static OffsetDateTimeTypeAdapter offsetDateTimeTypeAdapter = new OffsetDateTimeTypeAdapter();
private static LocalDateTypeAdapter localDateTypeAdapter = new LocalDateTypeAdapter();
private static LocalDateTimeTypeAdapter localDateTimeTypeAdapter = new LocalDateTimeTypeAdapter();
{{/jsr310}}
private static ByteArrayAdapter byteArrayAdapter = new ByteArrayAdapter();

Expand Down Expand Up @@ -125,6 +128,7 @@ public class JSON {
{{#jsr310}}
gsonBuilder.registerTypeAdapter(OffsetDateTime.class, offsetDateTimeTypeAdapter);
gsonBuilder.registerTypeAdapter(LocalDate.class, localDateTypeAdapter);
gsonBuilder.registerTypeAdapter(LocalDateTime.class, localDateTimeTypeAdapter);
{{/jsr310}}
gsonBuilder.registerTypeAdapter(byte[].class, byteArrayAdapter);
{{#models}}
Expand Down Expand Up @@ -431,6 +435,55 @@ public class JSON {
}
}

/**
* Gson TypeAdapter for JSR310 LocalDateTime type
*/
public static class LocalDateTimeTypeAdapter extends TypeAdapter<LocalDateTime> {

private DateTimeFormatter formatter;

public LocalDateTimeTypeAdapter() {
this(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
}

public LocalDateTimeTypeAdapter(DateTimeFormatter formatter) {
this.formatter = formatter;
}

public void setFormat(DateTimeFormatter dateFormat) {
this.formatter = dateFormat;
}

@Override
public void write(JsonWriter out, LocalDateTime date) throws IOException {
if (date == null) {
out.nullValue();
} else {
out.value(formatter.format(date));
}
}

@Override
public LocalDateTime read(JsonReader in) throws IOException {
switch (in.peek()) {
case NULL:
in.nextNull();
return null;
default:
String date = in.nextString();
try {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P3: For the space-separated format this PR is adding, read() now treats a parse failure as the expected path: every space-separated LocalDateTime must first throw and catch a DateTimeParseException, then reparse after rewriting the space to 'T'. A server that consistently emits RFC 3339 space-separated datetimes (e.g. 2016-09-09 08:02:03) will pay the cost of constructing and unwinding an exception for each and every field, rather than on rare error cases. The typical 'T'-separated path is the fast path, so impact is limited, but it may be worth normalizing the separator up front (e.g. checking charAt(10) before the first parse) while still only doing so when the formatter can accept it, to avoid exception-based control flow on the supported input format.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/JSON.mustache, line 474:

<comment>For the space-separated format this PR is adding, `read()` now treats a parse failure as the expected path: every space-separated `LocalDateTime` must first throw and catch a `DateTimeParseException`, then reparse after rewriting the space to 'T'. A server that consistently emits RFC 3339 space-separated datetimes (e.g. `2016-09-09 08:02:03`) will pay the cost of constructing and unwinding an exception for each and every field, rather than on rare error cases. The typical 'T'-separated path is the fast path, so impact is limited, but it may be worth normalizing the separator up front (e.g. checking `charAt(10)` before the first parse) while still only doing so when the formatter can accept it, to avoid exception-based control flow on the supported input format.</comment>

<file context>
@@ -470,11 +471,15 @@ public class JSON {
-                    // RFC 3339 section 5.6 permits a space in place of the ISO 8601 'T' separator
-                    if (date.length() > 10 && date.charAt(10) == ' ') {
-                        date = date.substring(0, 10) + 'T' + date.substring(11);
+                    try {
+                        return LocalDateTime.parse(date, formatter);
+                    } catch (DateTimeParseException e) {
</file context>

return LocalDateTime.parse(date, formatter);
} catch (DateTimeParseException e) {
if (date.length() > 10 && date.charAt(10) == ' ') {
date = date.substring(0, 10) + 'T' + date.substring(11);
return LocalDateTime.parse(date, formatter);
}
throw e;
}
}
}
}

public static void setOffsetDateTimeFormat(DateTimeFormatter dateFormat) {
offsetDateTimeTypeAdapter.setFormat(dateFormat);
}
Expand All @@ -439,6 +492,10 @@ public class JSON {
localDateTypeAdapter.setFormat(dateFormat);
}

public static void setLocalDateTimeFormat(DateTimeFormatter dateFormat) {
localDateTimeTypeAdapter.setFormat(dateFormat);
}

{{/jsr310}}
/**
* Gson TypeAdapter for java.sql.Date type
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,17 @@ public ApiClient setLocalDateFormat(DateTimeFormatter dateFormat) {
return this;
}

/**
* <p>Set LocalDateTimeFormat.</p>
*
* @param dateFormat a {@link java.time.format.DateTimeFormatter} object
* @return a {@link org.openapitools.client.ApiClient} object
*/
public ApiClient setLocalDateTimeFormat(DateTimeFormatter dateFormat) {
JSON.setLocalDateTimeFormat(dateFormat);
return this;
}

/**
* <p>Set LenientOnJson.</p>
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@
import java.text.ParseException;
import java.text.ParsePosition;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Date;
import java.util.Locale;
import java.util.Map;
Expand All @@ -56,6 +58,7 @@ public class JSON {
private static SqlDateTypeAdapter sqlDateTypeAdapter = new SqlDateTypeAdapter();
private static OffsetDateTimeTypeAdapter offsetDateTimeTypeAdapter = new OffsetDateTimeTypeAdapter();
private static LocalDateTypeAdapter localDateTypeAdapter = new LocalDateTypeAdapter();
private static LocalDateTimeTypeAdapter localDateTimeTypeAdapter = new LocalDateTimeTypeAdapter();
private static ByteArrayAdapter byteArrayAdapter = new ByteArrayAdapter();

@SuppressWarnings("unchecked")
Expand Down Expand Up @@ -95,6 +98,7 @@ private static Class getClassByDiscriminator(Map classByDiscriminatorValue, Stri
gsonBuilder.registerTypeAdapter(java.sql.Date.class, sqlDateTypeAdapter);
gsonBuilder.registerTypeAdapter(OffsetDateTime.class, offsetDateTimeTypeAdapter);
gsonBuilder.registerTypeAdapter(LocalDate.class, localDateTypeAdapter);
gsonBuilder.registerTypeAdapter(LocalDateTime.class, localDateTimeTypeAdapter);
gsonBuilder.registerTypeAdapter(byte[].class, byteArrayAdapter);
gsonBuilder.registerTypeAdapterFactory(new org.openapitools.client.model.Category.CustomTypeAdapterFactory());
gsonBuilder.registerTypeAdapterFactory(new org.openapitools.client.model.ModelApiResponse.CustomTypeAdapterFactory());
Expand Down Expand Up @@ -302,6 +306,55 @@ public LocalDate read(JsonReader in) throws IOException {
}
}

/**
* Gson TypeAdapter for JSR310 LocalDateTime type
*/
public static class LocalDateTimeTypeAdapter extends TypeAdapter<LocalDateTime> {

private DateTimeFormatter formatter;

public LocalDateTimeTypeAdapter() {
this(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
}

public LocalDateTimeTypeAdapter(DateTimeFormatter formatter) {
this.formatter = formatter;
}

public void setFormat(DateTimeFormatter dateFormat) {
this.formatter = dateFormat;
}

@Override
public void write(JsonWriter out, LocalDateTime date) throws IOException {
if (date == null) {
out.nullValue();
} else {
out.value(formatter.format(date));
}
}

@Override
public LocalDateTime read(JsonReader in) throws IOException {
switch (in.peek()) {
case NULL:
in.nextNull();
return null;
default:
String date = in.nextString();
try {
return LocalDateTime.parse(date, formatter);
} catch (DateTimeParseException e) {
if (date.length() > 10 && date.charAt(10) == ' ') {
date = date.substring(0, 10) + 'T' + date.substring(11);
return LocalDateTime.parse(date, formatter);
}
throw e;
}
}
}
}

public static void setOffsetDateTimeFormat(DateTimeFormatter dateFormat) {
offsetDateTimeTypeAdapter.setFormat(dateFormat);
}
Expand All @@ -310,6 +363,10 @@ public static void setLocalDateFormat(DateTimeFormatter dateFormat) {
localDateTypeAdapter.setFormat(dateFormat);
}

public static void setLocalDateTimeFormat(DateTimeFormatter dateFormat) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: Generated clients cannot configure the new LocalDateTime formatter through ApiClient, unlike the existing date and offset-date-time format settings. Adding the matching ApiClient forwarding method (and regenerating this sample) would make the new public JSON setting usable through the standard client entry point.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/echo_api/java/okhttp-gson-user-defined-templates/src/main/java/org/openapitools/client/JSON.java, line 361:

<comment>Generated clients cannot configure the new LocalDateTime formatter through `ApiClient`, unlike the existing date and offset-date-time format settings. Adding the matching `ApiClient` forwarding method (and regenerating this sample) would make the new public JSON setting usable through the standard client entry point.</comment>

<file context>
@@ -310,6 +358,10 @@ public static void setLocalDateFormat(DateTimeFormatter dateFormat) {
         localDateTypeAdapter.setFormat(dateFormat);
     }
 
+    public static void setLocalDateTimeFormat(DateTimeFormatter dateFormat) {
+        localDateTimeTypeAdapter.setFormat(dateFormat);
+    }
</file context>

localDateTimeTypeAdapter.setFormat(dateFormat);
}

/**
* Gson TypeAdapter for java.sql.Date type
* If the dateFormat is null, a simple "yyyy-MM-dd" format will be used
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,17 @@ public ApiClient setLocalDateFormat(DateTimeFormatter dateFormat) {
return this;
}

/**
* <p>Set LocalDateTimeFormat.</p>
*
* @param dateFormat a {@link java.time.format.DateTimeFormatter} object
* @return a {@link org.openapitools.client.ApiClient} object
*/
public ApiClient setLocalDateTimeFormat(DateTimeFormatter dateFormat) {
JSON.setLocalDateTimeFormat(dateFormat);
return this;
}

/**
* <p>Set LenientOnJson.</p>
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@
import java.text.ParseException;
import java.text.ParsePosition;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Date;
import java.util.Locale;
import java.util.Map;
Expand All @@ -56,6 +58,7 @@ public class JSON {
private static SqlDateTypeAdapter sqlDateTypeAdapter = new SqlDateTypeAdapter();
private static OffsetDateTimeTypeAdapter offsetDateTimeTypeAdapter = new OffsetDateTimeTypeAdapter();
private static LocalDateTypeAdapter localDateTypeAdapter = new LocalDateTypeAdapter();
private static LocalDateTimeTypeAdapter localDateTimeTypeAdapter = new LocalDateTimeTypeAdapter();
private static ByteArrayAdapter byteArrayAdapter = new ByteArrayAdapter();

@SuppressWarnings("unchecked")
Expand Down Expand Up @@ -95,6 +98,7 @@ private static Class getClassByDiscriminator(Map classByDiscriminatorValue, Stri
gsonBuilder.registerTypeAdapter(java.sql.Date.class, sqlDateTypeAdapter);
gsonBuilder.registerTypeAdapter(OffsetDateTime.class, offsetDateTimeTypeAdapter);
gsonBuilder.registerTypeAdapter(LocalDate.class, localDateTypeAdapter);
gsonBuilder.registerTypeAdapter(LocalDateTime.class, localDateTimeTypeAdapter);
gsonBuilder.registerTypeAdapter(byte[].class, byteArrayAdapter);
gsonBuilder.registerTypeAdapterFactory(new org.openapitools.client.model.Bird.CustomTypeAdapterFactory());
gsonBuilder.registerTypeAdapterFactory(new org.openapitools.client.model.Category.CustomTypeAdapterFactory());
Expand Down Expand Up @@ -306,6 +310,55 @@ public LocalDate read(JsonReader in) throws IOException {
}
}

/**
* Gson TypeAdapter for JSR310 LocalDateTime type
*/
public static class LocalDateTimeTypeAdapter extends TypeAdapter<LocalDateTime> {

private DateTimeFormatter formatter;

public LocalDateTimeTypeAdapter() {
this(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
}

public LocalDateTimeTypeAdapter(DateTimeFormatter formatter) {
this.formatter = formatter;
}

public void setFormat(DateTimeFormatter dateFormat) {
this.formatter = dateFormat;
}

@Override
public void write(JsonWriter out, LocalDateTime date) throws IOException {
if (date == null) {
out.nullValue();
} else {
out.value(formatter.format(date));
}
}

@Override
public LocalDateTime read(JsonReader in) throws IOException {
switch (in.peek()) {
case NULL:
in.nextNull();
return null;
default:
String date = in.nextString();
try {
return LocalDateTime.parse(date, formatter);
} catch (DateTimeParseException e) {
if (date.length() > 10 && date.charAt(10) == ' ') {
date = date.substring(0, 10) + 'T' + date.substring(11);
return LocalDateTime.parse(date, formatter);
}
throw e;
}
}
}
}

public static void setOffsetDateTimeFormat(DateTimeFormatter dateFormat) {
offsetDateTimeTypeAdapter.setFormat(dateFormat);
}
Expand All @@ -314,6 +367,10 @@ public static void setLocalDateFormat(DateTimeFormatter dateFormat) {
localDateTypeAdapter.setFormat(dateFormat);
}

public static void setLocalDateTimeFormat(DateTimeFormatter dateFormat) {
localDateTimeTypeAdapter.setFormat(dateFormat);
}

/**
* Gson TypeAdapter for java.sql.Date type
* If the dateFormat is null, a simple "yyyy-MM-dd" format will be used
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,17 @@ public ApiClient setLocalDateFormat(DateTimeFormatter dateFormat) {
return this;
}

/**
* <p>Set LocalDateTimeFormat.</p>
*
* @param dateFormat a {@link java.time.format.DateTimeFormatter} object
* @return a {@link org.openapitools.client.ApiClient} object
*/
public ApiClient setLocalDateTimeFormat(DateTimeFormatter dateFormat) {
JSON.setLocalDateTimeFormat(dateFormat);
return this;
}

/**
* <p>Set LenientOnJson.</p>
*
Expand Down
Loading
Loading