diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractJavaCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractJavaCodegen.java index cabd29103538..4de984e5cf35 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractJavaCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractJavaCodegen.java @@ -260,6 +260,7 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code } if("joda".equals(dateLibrary)) { + additionalProperties.put("joda", "true"); typeMapping.put("date", "LocalDate"); typeMapping.put("DateTime", "DateTime"); diff --git a/modules/swagger-codegen/src/main/resources/Java/libraries/okhttp-gson/ApiClient.mustache b/modules/swagger-codegen/src/main/resources/Java/libraries/okhttp-gson/ApiClient.mustache index 9c75d6716077..f0b4cc64334c 100644 --- a/modules/swagger-codegen/src/main/resources/Java/libraries/okhttp-gson/ApiClient.mustache +++ b/modules/swagger-codegen/src/main/resources/Java/libraries/okhttp-gson/ApiClient.mustache @@ -2,43 +2,26 @@ package {{invokerPackage}}; -import com.squareup.okhttp.Call; -import com.squareup.okhttp.Callback; -import com.squareup.okhttp.OkHttpClient; -import com.squareup.okhttp.Request; -import com.squareup.okhttp.Response; -import com.squareup.okhttp.RequestBody; -import com.squareup.okhttp.FormEncodingBuilder; -import com.squareup.okhttp.MultipartBuilder; -import com.squareup.okhttp.MediaType; -import com.squareup.okhttp.Headers; +import com.squareup.okhttp.*; import com.squareup.okhttp.internal.http.HttpMethod; import com.squareup.okhttp.logging.HttpLoggingInterceptor; import com.squareup.okhttp.logging.HttpLoggingInterceptor.Level; +import okio.BufferedSink; +import okio.Okio; +{{#joda}} +import org.joda.time.DateTime; +import org.joda.time.LocalDate; +import org.joda.time.format.DateTimeFormatter; +{{/joda}} -import java.lang.reflect.Type; - -import java.util.Collection; -import java.util.Collections; -import java.util.Map; -import java.util.Map.Entry; -import java.util.HashMap; -import java.util.List; -import java.util.ArrayList; -import java.util.Date; -import java.util.TimeZone; -import java.util.concurrent.TimeUnit; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import java.net.URLEncoder; -import java.net.URLConnection; - +import javax.net.ssl.*; import java.io.File; -import java.io.InputStream; import java.io.IOException; +import java.io.InputStream; import java.io.UnsupportedEncodingException; - +import java.lang.reflect.Type; +import java.net.URLConnection; +import java.net.URLEncoder; import java.security.GeneralSecurityException; import java.security.KeyStore; import java.security.SecureRandom; @@ -46,22 +29,17 @@ import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; - import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.text.ParseException; - -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.KeyManager; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSession; -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactory; -import javax.net.ssl.X509TrustManager; - -import okio.BufferedSink; -import okio.Okio; +{{#java8}} +import java.time.LocalDate; +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; +{{/java8}} +import java.util.*; +import java.util.Map.Entry; +import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import {{invokerPackage}}.auth.Authentication; import {{invokerPackage}}.auth.HttpBasicAuth; @@ -69,51 +47,14 @@ import {{invokerPackage}}.auth.ApiKeyAuth; import {{invokerPackage}}.auth.OAuth; public class ApiClient { - public static final double JAVA_VERSION; - public static final boolean IS_ANDROID; - public static final int ANDROID_SDK_VERSION; - - static { - JAVA_VERSION = Double.parseDouble(System.getProperty("java.specification.version")); - boolean isAndroid; - try { - Class.forName("android.app.Activity"); - isAndroid = true; - } catch (ClassNotFoundException e) { - isAndroid = false; - } - IS_ANDROID = isAndroid; - int sdkVersion = 0; - if (IS_ANDROID) { - try { - sdkVersion = Class.forName("android.os.Build$VERSION").getField("SDK_INT").getInt(null); - } catch (Exception e) { - try { - sdkVersion = Integer.parseInt((String) Class.forName("android.os.Build$VERSION").getField("SDK").get(null)); - } catch (Exception e2) { } - } - } - ANDROID_SDK_VERSION = sdkVersion; - } - - /** - * The datetime format to be used when lenientDatetimeFormat is enabled. - */ - public static final String LENIENT_DATETIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"; private String basePath = "{{{basePath}}}"; - private boolean lenientOnJson = false; private boolean debugging = false; private Map defaultHeaderMap = new HashMap(); private String tempFolderPath = null; private Map authentications; - private DateFormat dateFormat; - private DateFormat datetimeFormat; - private boolean lenientDatetimeFormat; - private int dateLength; - private InputStream sslCaCert; private boolean verifyingSsl; @@ -127,23 +68,8 @@ public class ApiClient { */ public ApiClient() { httpClient = new OkHttpClient(); - verifyingSsl = true; - - json = new JSON(this); - - /* - * Use RFC3339 format for date and datetime. - * See http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14 - */ - this.dateFormat = new SimpleDateFormat("yyyy-MM-dd"); - // Always use UTC as the default time zone when dealing with date (without time). - this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); - initDatetimeFormat(); - - // Be lenient on datetime formats when parsing datetime from string. - // See parseDatetime. - this.lenientDatetimeFormat = true; + json = new JSON(); // Set default User-Agent. setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}Swagger-Codegen/{{{artifactVersion}}}/java{{/httpUserAgent}}"); @@ -262,143 +188,43 @@ public class ApiClient { return this; } - public DateFormat getDateFormat() { - return dateFormat; - } - public ApiClient setDateFormat(DateFormat dateFormat) { - this.dateFormat = dateFormat; - this.dateLength = this.dateFormat.format(new Date()).length(); + this.json.setDateFormat(dateFormat); return this; } - public DateFormat getDatetimeFormat() { - return datetimeFormat; - } - - public ApiClient setDatetimeFormat(DateFormat datetimeFormat) { - this.datetimeFormat = datetimeFormat; + public ApiClient setSqlDateFormat(DateFormat dateFormat) { + this.json.setSqlDateFormat(dateFormat); return this; } - /** - * Whether to allow various ISO 8601 datetime formats when parsing a datetime string. - * @see #parseDatetime(String) - * @return True if lenientDatetimeFormat flag is set to true - */ - public boolean isLenientDatetimeFormat() { - return lenientDatetimeFormat; - } - - public ApiClient setLenientDatetimeFormat(boolean lenientDatetimeFormat) { - this.lenientDatetimeFormat = lenientDatetimeFormat; + {{#joda}} + public ApiClient setDateTimeFormat(DateTimeFormatter dateFormat) { + this.json.setDateTimeFormat(dateFormat); return this; } - /** - * Parse the given date string into Date object. - * The default dateFormat supports these ISO 8601 date formats: - * 2015-08-16 - * 2015-8-16 - * @param str String to be parsed - * @return Date - */ - public Date parseDate(String str) { - if (str == null) - return null; - try { - return dateFormat.parse(str); - } catch (ParseException e) { - throw new RuntimeException(e); - } + public ApiClient setLocalDateFormat(DateTimeFormatter dateFormat) { + this.json.setLocalDateFormat(dateFormat); + return this; } - /** - * Parse the given datetime string into Date object. - * When lenientDatetimeFormat is enabled, the following ISO 8601 datetime formats are supported: - * 2015-08-16T08:20:05Z - * 2015-8-16T8:20:05Z - * 2015-08-16T08:20:05+00:00 - * 2015-08-16T08:20:05+0000 - * 2015-08-16T08:20:05.376Z - * 2015-08-16T08:20:05.376+00:00 - * 2015-08-16T08:20:05.376+00 - * Note: The 3-digit milli-seconds is optional. Time zone is required and can be in one of - * these formats: - * Z (same with +0000) - * +08:00 (same with +0800) - * -02 (same with -0200) - * -0200 - * @see ISO 8601 - * @param str Date time string to be parsed - * @return Date representation of the string - */ - public Date parseDatetime(String str) { - if (str == null) - return null; - - DateFormat format; - if (lenientDatetimeFormat) { - /* - * When lenientDatetimeFormat is enabled, normalize the date string - * into LENIENT_DATETIME_FORMAT to support various formats - * defined by ISO 8601. - */ - // normalize time zone - // trailing "Z": 2015-08-16T08:20:05Z => 2015-08-16T08:20:05+0000 - str = str.replaceAll("[zZ]\\z", "+0000"); - // remove colon in time zone: 2015-08-16T08:20:05+00:00 => 2015-08-16T08:20:05+0000 - str = str.replaceAll("([+-]\\d{2}):(\\d{2})\\z", "$1$2"); - // expand time zone: 2015-08-16T08:20:05+00 => 2015-08-16T08:20:05+0000 - str = str.replaceAll("([+-]\\d{2})\\z", "$100"); - // add milliseconds when missing - // 2015-08-16T08:20:05+0000 => 2015-08-16T08:20:05.000+0000 - str = str.replaceAll("(:\\d{1,2})([+-]\\d{4})\\z", "$1.000$2"); - format = new SimpleDateFormat(LENIENT_DATETIME_FORMAT); - } else { - format = this.datetimeFormat; - } - - try { - return format.parse(str); - } catch (ParseException e) { - throw new RuntimeException(e); - } + {{/joda}} + {{#java8}} + public ApiClient setOffsetDateTimeFormat(DateTimeFormatter dateFormat) { + this.json.setOffsetDateTimeFormat(dateFormat); + return this; } - /* - * Parse date or date time in string format into Date object. - * - * @param str Date time string to be parsed - * @return Date representation of the string - */ - public Date parseDateOrDatetime(String str) { - if (str == null) - return null; - else if (str.length() <= dateLength) - return parseDate(str); - else - return parseDatetime(str); + public ApiClient setLocalDateFormat(DateTimeFormatter dateFormat) { + this.json.setLocalDateFormat(dateFormat); + return this; } - /** - * Format the given Date object into string (Date format). - * - * @param date Date object - * @return Formatted date in string representation - */ - public String formatDate(Date date) { - return dateFormat.format(date); - } - - /** - * Format the given Date object into string (Datetime format). - * - * @param date Date object - * @return Formatted datetime in string representation - */ - public String formatDatetime(Date date) { - return datetimeFormat.format(date); + {{/java8}} + public ApiClient setLenientOnJson(boolean lenientOnJson) { + this.json.setLenientOnJson(lenientOnJson); + return this; } /** @@ -518,26 +344,6 @@ public class ApiClient { return this; } - /** - * @see setLenient - * - * @return True if lenientOnJson is enabled, false otherwise. - */ - public boolean isLenientOnJson() { - return lenientOnJson; - } - - /** - * Set LenientOnJson - * - * @param lenient True to enable lenientOnJson - * @return ApiClient - */ - public ApiClient setLenientOnJson(boolean lenient) { - this.lenientOnJson = lenient; - return this; - } - /** * Check that whether debugging is enabled for this API client. * @@ -621,8 +427,10 @@ public class ApiClient { public String parameterToString(Object param) { if (param == null) { return ""; - } else if (param instanceof Date) { - return formatDatetime((Date) param); + } else if (param instanceof Date {{#joda}}|| param instanceof DateTime || param instanceof LocalDate{{/joda}}{{#java8}}|| param instanceof OffsetDateTime || param instanceof LocalDate{{/java8}}) { + //Serialize to json string and remove the " enclosing characters + String jsonStr = json.serialize(param); + return jsonStr.substring(1, jsonStr.length() - 1); } else if (param instanceof Collection) { StringBuilder b = new StringBuilder(); for (Object o : (Collection)param) { @@ -1212,31 +1020,6 @@ public class ApiClient { } } - /** - * Initialize datetime format according to the current environment, e.g. Java 1.7 and Android. - */ - private void initDatetimeFormat() { - String formatWithTimeZone = null; - if (IS_ANDROID) { - if (ANDROID_SDK_VERSION >= 18) { - // The time zone format "ZZZZZ" is available since Android 4.3 (SDK version 18) - formatWithTimeZone = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"; - } - } else if (JAVA_VERSION >= 1.7) { - // The time zone format "XXX" is available since Java 1.7 - formatWithTimeZone = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX"; - } - if (formatWithTimeZone != null) { - this.datetimeFormat = new SimpleDateFormat(formatWithTimeZone); - // NOTE: Use the system's default time zone (mainly for datetime formatting). - } else { - // Use a common format that works across all systems. - this.datetimeFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); - // Always use the UTC time zone as we are using a constant trailing "Z" here. - this.datetimeFormat.setTimeZone(TimeZone.getTimeZone("UTC")); - } - } - /** * Apply SSL related settings to httpClient according to the current values of * verifyingSsl and sslCaCert. diff --git a/modules/swagger-codegen/src/main/resources/Java/libraries/okhttp-gson/JSON.mustache b/modules/swagger-codegen/src/main/resources/Java/libraries/okhttp-gson/JSON.mustache index 06f26da304bb..d43376a992ce 100644 --- a/modules/swagger-codegen/src/main/resources/Java/libraries/okhttp-gson/JSON.mustache +++ b/modules/swagger-codegen/src/main/resources/Java/libraries/okhttp-gson/JSON.mustache @@ -4,55 +4,57 @@ package {{invokerPackage}}; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonNull; import com.google.gson.JsonParseException; -import com.google.gson.JsonPrimitive; -import com.google.gson.JsonSerializationContext; -import com.google.gson.JsonSerializer; import com.google.gson.TypeAdapter; +import com.google.gson.internal.bind.util.ISO8601Utils; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; - -import java.io.IOException; -import java.io.StringReader; -import java.lang.reflect.Type; -import java.util.Date; - -{{^java8}} +{{#joda}} import org.joda.time.DateTime; import org.joda.time.LocalDate; import org.joda.time.format.DateTimeFormatter; import org.joda.time.format.ISODateTimeFormat; -{{/java8}} +{{/joda}} + +import java.io.IOException; +import java.io.StringReader; +import java.lang.reflect.Type; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.ParsePosition; {{#java8}} import java.time.LocalDate; import java.time.OffsetDateTime; import java.time.format.DateTimeFormatter; {{/java8}} +import java.util.Date; public class JSON { - private ApiClient apiClient; private Gson gson; + private boolean isLenientOnJson = false; + private DateTypeAdapter dateTypeAdapter = new DateTypeAdapter(); + private SqlDateTypeAdapter sqlDateTypeAdapter = new SqlDateTypeAdapter(); + {{#joda}} + private DateTimeTypeAdapter dateTimeTypeAdapter = new DateTimeTypeAdapter(); + private LocalDateTypeAdapter localDateTypeAdapter = new LocalDateTypeAdapter(); + {{/joda}} + {{#java8}} + private OffsetDateTimeTypeAdapter offsetDateTimeTypeAdapter = new OffsetDateTimeTypeAdapter(); + private LocalDateTypeAdapter localDateTypeAdapter = new LocalDateTypeAdapter(); + {{/java8}} - /** - * JSON constructor. - * - * @param apiClient An instance of ApiClient - */ - public JSON(ApiClient apiClient) { - this.apiClient = apiClient; + public JSON() { gson = new GsonBuilder() - .registerTypeAdapter(Date.class, new DateAdapter(apiClient)) - {{^java8}} - .registerTypeAdapter(DateTime.class, new DateTimeTypeAdapter()) - {{/java8}} + .registerTypeAdapter(Date.class, dateTypeAdapter) + .registerTypeAdapter(java.sql.Date.class, sqlDateTypeAdapter) + {{#joda}} + .registerTypeAdapter(DateTime.class, dateTimeTypeAdapter) + .registerTypeAdapter(LocalDate.class, localDateTypeAdapter) + {{/joda}} {{#java8}} - .registerTypeAdapter(OffsetDateTime.class, new OffsetDateTimeTypeAdapter()) + .registerTypeAdapter(OffsetDateTime.class, offsetDateTimeTypeAdapter) + .registerTypeAdapter(LocalDate.class, localDateTypeAdapter) {{/java8}} - .registerTypeAdapter(LocalDate.class, new LocalDateTypeAdapter()) .create(); } @@ -70,8 +72,14 @@ public class JSON { * * @param gson Gson */ - public void setGson(Gson gson) { + public JSON setGson(Gson gson) { this.gson = gson; + return this; + } + + public JSON setLenientOnJson(boolean lenientOnJson) { + isLenientOnJson = lenientOnJson; + return this; } /** @@ -87,15 +95,15 @@ public class JSON { /** * Deserialize the given JSON string to Java object. * - * @param Type - * @param body The JSON string + * @param Type + * @param body The JSON string * @param returnType The type to deserialize into * @return The deserialized Java object */ @SuppressWarnings("unchecked") public T deserialize(String body, Type returnType) { try { - if (apiClient.isLenientOnJson()) { + if (isLenientOnJson) { JsonReader jsonReader = new JsonReader(new StringReader(body)); // see https://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/stream/JsonReader.html#setLenient(boolean) jsonReader.setLenient(true); @@ -105,186 +113,325 @@ public class JSON { } } catch (JsonParseException e) { // Fallback processing when failed to parse JSON form response body: - // return the response body string directly for the String return type; - // parse response body into date or datetime for the Date return type. + // return the response body string directly for the String return type; if (returnType.equals(String.class)) return (T) body; - else if (returnType.equals(Date.class)) - return (T) apiClient.parseDateOrDatetime(body); - else throw(e); + else throw (e); } } -} - -class DateAdapter implements JsonSerializer, JsonDeserializer { - private final ApiClient apiClient; + {{#joda}} /** - * Constructor for DateAdapter - * - * @param apiClient Api client + * Gson TypeAdapter for Joda DateTime type */ - public DateAdapter(ApiClient apiClient) { - super(); - this.apiClient = apiClient; - } + public static class DateTimeTypeAdapter extends TypeAdapter { - /** - * Serialize - * - * @param src Date - * @param typeOfSrc Type - * @param context Json Serialization Context - * @return Json Element - */ - @Override - public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) { - if (src == null) { - return JsonNull.INSTANCE; - } else { - return new JsonPrimitive(apiClient.formatDatetime(src)); + private DateTimeFormatter formatter; + + public DateTimeTypeAdapter() { + this(ISODateTimeFormat.dateTime().withOffsetParsed()); + } + + public DateTimeTypeAdapter(DateTimeFormatter formatter) { + this.formatter = formatter; + } + + public void setFormat(DateTimeFormatter dateFormat) { + this.formatter = dateFormat; + } + + @Override + public void write(JsonWriter out, DateTime date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + out.value(formatter.print(date)); + } + } + + @Override + public DateTime read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + return formatter.parseDateTime(date); + } } } /** - * Deserialize - * - * @param json Json element - * @param date Type - * @param context Json Serialization Context - * @return Date - * @throws JsonParseException if fail to parse + * Gson TypeAdapter for Joda LocalDate type */ - @Override - public Date deserialize(JsonElement json, Type date, JsonDeserializationContext context) throws JsonParseException { - String str = json.getAsJsonPrimitive().getAsString(); - try { - return apiClient.parseDateOrDatetime(str); - } catch (RuntimeException e) { - throw new JsonParseException(e); + public class LocalDateTypeAdapter extends TypeAdapter { + + private DateTimeFormatter formatter; + + public LocalDateTypeAdapter() { + this(ISODateTimeFormat.date()); } - } -} -{{^java8}} -/** - * Gson TypeAdapter for Joda DateTime type - */ -class DateTimeTypeAdapter extends TypeAdapter { + public LocalDateTypeAdapter(DateTimeFormatter formatter) { + this.formatter = formatter; + } - private final DateTimeFormatter formatter = ISODateTimeFormat.dateTime(); + public void setFormat(DateTimeFormatter dateFormat) { + this.formatter = dateFormat; + } - @Override - public void write(JsonWriter out, DateTime date) throws IOException { - if (date == null) { - out.nullValue(); - } else { - out.value(formatter.print(date)); + @Override + public void write(JsonWriter out, LocalDate date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + out.value(formatter.print(date)); + } + } + + @Override + public LocalDate read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + return formatter.parseLocalDate(date); + } } } - @Override - public DateTime read(JsonReader in) throws IOException { - switch (in.peek()) { - case NULL: - in.nextNull(); - return null; - default: - String date = in.nextString(); - return formatter.parseDateTime(date); - } + public JSON setDateTimeFormat(DateTimeFormatter dateFormat) { + dateTimeTypeAdapter.setFormat(dateFormat); + return this; } -} -/** - * Gson TypeAdapter for Joda LocalDate type - */ -class LocalDateTypeAdapter extends TypeAdapter { + public JSON setLocalDateFormat(DateTimeFormatter dateFormat) { + localDateTypeAdapter.setFormat(dateFormat); + return this; + } - private final DateTimeFormatter formatter = ISODateTimeFormat.date(); + {{/joda}} + {{#java8}} + /** + * Gson TypeAdapter for JSR310 OffsetDateTime type + */ + public static class OffsetDateTimeTypeAdapter extends TypeAdapter { - @Override - public void write(JsonWriter out, LocalDate date) throws IOException { - if (date == null) { - out.nullValue(); - } else { - out.value(formatter.print(date)); + private DateTimeFormatter formatter; + + public OffsetDateTimeTypeAdapter() { + this(DateTimeFormatter.ISO_OFFSET_DATE_TIME); + } + + public OffsetDateTimeTypeAdapter(DateTimeFormatter formatter) { + this.formatter = formatter; + } + + public void setFormat(DateTimeFormatter dateFormat) { + this.formatter = dateFormat; + } + + @Override + public void write(JsonWriter out, OffsetDateTime date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + out.value(formatter.format(date)); + } + } + + @Override + public OffsetDateTime read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + if (date.endsWith("+0000")) { + date = date.substring(0, date.length()-5) + "Z"; + } + return OffsetDateTime.parse(date, formatter); + } } } - @Override - public LocalDate read(JsonReader in) throws IOException { - switch (in.peek()) { - case NULL: - in.nextNull(); - return null; - default: - String date = in.nextString(); - return formatter.parseLocalDate(date); + /** + * Gson TypeAdapter for JSR310 LocalDate type + */ + public class LocalDateTypeAdapter extends TypeAdapter { + + private DateTimeFormatter formatter; + + public LocalDateTypeAdapter() { + this(DateTimeFormatter.ISO_LOCAL_DATE); } - } -} -{{/java8}} -{{#java8}} -/** - * Gson TypeAdapter for jsr310 OffsetDateTime type - */ -class OffsetDateTimeTypeAdapter extends TypeAdapter { - private final DateTimeFormatter formatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME; + public LocalDateTypeAdapter(DateTimeFormatter formatter) { + this.formatter = formatter; + } - @Override - public void write(JsonWriter out, OffsetDateTime date) throws IOException { - if (date == null) { - out.nullValue(); - } else { - out.value(formatter.format(date)); + public void setFormat(DateTimeFormatter dateFormat) { + this.formatter = dateFormat; + } + + @Override + public void write(JsonWriter out, LocalDate date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + out.value(formatter.format(date)); + } + } + + @Override + public LocalDate read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + return LocalDate.parse(date, formatter); + } } } - @Override - public OffsetDateTime read(JsonReader in) throws IOException { - switch (in.peek()) { - case NULL: - in.nextNull(); - return null; - default: - String date = in.nextString(); - if (date.endsWith("+0000")) { - date = date.substring(0, date.length()-5) + "Z"; + public JSON setOffsetDateTimeFormat(DateTimeFormatter dateFormat) { + offsetDateTimeTypeAdapter.setFormat(dateFormat); + return this; + } + + public JSON setLocalDateFormat(DateTimeFormatter dateFormat) { + localDateTypeAdapter.setFormat(dateFormat); + return this; + } + + {{/java8}} + /** + * Gson TypeAdapter for java.sql.Date type + * If the dateFormat is null, a simple "yyyy-MM-dd" format will be used + * (more efficient than SimpleDateFormat). + */ + public static class SqlDateTypeAdapter extends TypeAdapter { + + private DateFormat dateFormat; + + public SqlDateTypeAdapter() { + } + + public SqlDateTypeAdapter(DateFormat dateFormat) { + this.dateFormat = dateFormat; + } + + public void setFormat(DateFormat dateFormat) { + this.dateFormat = dateFormat; + } + + @Override + public void write(JsonWriter out, java.sql.Date date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + String value; + if (dateFormat != null) { + value = dateFormat.format(date); + } else { + value = date.toString(); } + out.value(value); + } + } - return OffsetDateTime.parse(date, formatter); + @Override + public java.sql.Date read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + try { + if (dateFormat != null) { + return new java.sql.Date(dateFormat.parse(date).getTime()); + } + return new java.sql.Date(ISO8601Utils.parse(date, new ParsePosition(0)).getTime()); + } catch (ParseException e) { + throw new JsonParseException(e); + } + } } } + + /** + * Gson TypeAdapter for java.util.Date type + * If the dateFormat is null, ISO8601Utils will be used. + */ + public static class DateTypeAdapter extends TypeAdapter { + + private DateFormat dateFormat; + + public DateTypeAdapter() { + } + + public DateTypeAdapter(DateFormat dateFormat) { + this.dateFormat = dateFormat; + } + + public void setFormat(DateFormat dateFormat) { + this.dateFormat = dateFormat; + } + + @Override + public void write(JsonWriter out, Date date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + String value; + if (dateFormat != null) { + value = dateFormat.format(date); + } else { + value = ISO8601Utils.format(date, true); + } + out.value(value); + } + } + + @Override + public Date read(JsonReader in) throws IOException { + try { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + try { + if (dateFormat != null) { + return dateFormat.parse(date); + } + return ISO8601Utils.parse(date, new ParsePosition(0)); + } catch (ParseException e) { + throw new JsonParseException(e); + } + } + } catch (IllegalArgumentException e) { + throw new JsonParseException(e); + } + } + } + + public JSON setDateFormat(DateFormat dateFormat) { + dateTypeAdapter.setFormat(dateFormat); + return this; + } + + public JSON setSqlDateFormat(DateFormat dateFormat) { + sqlDateTypeAdapter.setFormat(dateFormat); + return this; + } + } - -/** - * Gson TypeAdapter for jsr310 LocalDate type - */ -class LocalDateTypeAdapter extends TypeAdapter { - - private final DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE; - - @Override - public void write(JsonWriter out, LocalDate date) throws IOException { - if (date == null) { - out.nullValue(); - } else { - out.value(formatter.format(date)); - } - } - - @Override - public LocalDate read(JsonReader in) throws IOException { - switch (in.peek()) { - case NULL: - in.nextNull(); - return null; - default: - String date = in.nextString(); - return LocalDate.parse(date, formatter); - } - } -} -{{/java8}} diff --git a/samples/client/petstore/java/okhttp-gson/src/main/java/io/swagger/client/ApiClient.java b/samples/client/petstore/java/okhttp-gson/src/main/java/io/swagger/client/ApiClient.java index c4137dcb8169..0f388ea6e603 100644 --- a/samples/client/petstore/java/okhttp-gson/src/main/java/io/swagger/client/ApiClient.java +++ b/samples/client/petstore/java/okhttp-gson/src/main/java/io/swagger/client/ApiClient.java @@ -25,43 +25,24 @@ package io.swagger.client; -import com.squareup.okhttp.Call; -import com.squareup.okhttp.Callback; -import com.squareup.okhttp.OkHttpClient; -import com.squareup.okhttp.Request; -import com.squareup.okhttp.Response; -import com.squareup.okhttp.RequestBody; -import com.squareup.okhttp.FormEncodingBuilder; -import com.squareup.okhttp.MultipartBuilder; -import com.squareup.okhttp.MediaType; -import com.squareup.okhttp.Headers; +import com.squareup.okhttp.*; import com.squareup.okhttp.internal.http.HttpMethod; import com.squareup.okhttp.logging.HttpLoggingInterceptor; import com.squareup.okhttp.logging.HttpLoggingInterceptor.Level; +import okio.BufferedSink; +import okio.Okio; +import org.joda.time.DateTime; +import org.joda.time.LocalDate; +import org.joda.time.format.DateTimeFormatter; -import java.lang.reflect.Type; - -import java.util.Collection; -import java.util.Collections; -import java.util.Map; -import java.util.Map.Entry; -import java.util.HashMap; -import java.util.List; -import java.util.ArrayList; -import java.util.Date; -import java.util.TimeZone; -import java.util.concurrent.TimeUnit; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import java.net.URLEncoder; -import java.net.URLConnection; - +import javax.net.ssl.*; import java.io.File; -import java.io.InputStream; import java.io.IOException; +import java.io.InputStream; import java.io.UnsupportedEncodingException; - +import java.lang.reflect.Type; +import java.net.URLConnection; +import java.net.URLEncoder; import java.security.GeneralSecurityException; import java.security.KeyStore; import java.security.SecureRandom; @@ -69,22 +50,12 @@ import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; - import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.text.ParseException; - -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.KeyManager; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSession; -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactory; -import javax.net.ssl.X509TrustManager; - -import okio.BufferedSink; -import okio.Okio; +import java.util.*; +import java.util.Map.Entry; +import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import io.swagger.client.auth.Authentication; import io.swagger.client.auth.HttpBasicAuth; @@ -92,51 +63,14 @@ import io.swagger.client.auth.ApiKeyAuth; import io.swagger.client.auth.OAuth; public class ApiClient { - public static final double JAVA_VERSION; - public static final boolean IS_ANDROID; - public static final int ANDROID_SDK_VERSION; - - static { - JAVA_VERSION = Double.parseDouble(System.getProperty("java.specification.version")); - boolean isAndroid; - try { - Class.forName("android.app.Activity"); - isAndroid = true; - } catch (ClassNotFoundException e) { - isAndroid = false; - } - IS_ANDROID = isAndroid; - int sdkVersion = 0; - if (IS_ANDROID) { - try { - sdkVersion = Class.forName("android.os.Build$VERSION").getField("SDK_INT").getInt(null); - } catch (Exception e) { - try { - sdkVersion = Integer.parseInt((String) Class.forName("android.os.Build$VERSION").getField("SDK").get(null)); - } catch (Exception e2) { } - } - } - ANDROID_SDK_VERSION = sdkVersion; - } - - /** - * The datetime format to be used when lenientDatetimeFormat is enabled. - */ - public static final String LENIENT_DATETIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"; private String basePath = "http://petstore.swagger.io/v2"; - private boolean lenientOnJson = false; private boolean debugging = false; private Map defaultHeaderMap = new HashMap(); private String tempFolderPath = null; private Map authentications; - private DateFormat dateFormat; - private DateFormat datetimeFormat; - private boolean lenientDatetimeFormat; - private int dateLength; - private InputStream sslCaCert; private boolean verifyingSsl; @@ -150,23 +84,8 @@ public class ApiClient { */ public ApiClient() { httpClient = new OkHttpClient(); - verifyingSsl = true; - - json = new JSON(this); - - /* - * Use RFC3339 format for date and datetime. - * See http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14 - */ - this.dateFormat = new SimpleDateFormat("yyyy-MM-dd"); - // Always use UTC as the default time zone when dealing with date (without time). - this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); - initDatetimeFormat(); - - // Be lenient on datetime formats when parsing datetime from string. - // See parseDatetime. - this.lenientDatetimeFormat = true; + json = new JSON(); // Set default User-Agent. setUserAgent("Swagger-Codegen/1.0.0/java"); @@ -285,143 +204,29 @@ public class ApiClient { return this; } - public DateFormat getDateFormat() { - return dateFormat; - } - public ApiClient setDateFormat(DateFormat dateFormat) { - this.dateFormat = dateFormat; - this.dateLength = this.dateFormat.format(new Date()).length(); + this.json.setDateFormat(dateFormat); return this; } - public DateFormat getDatetimeFormat() { - return datetimeFormat; - } - - public ApiClient setDatetimeFormat(DateFormat datetimeFormat) { - this.datetimeFormat = datetimeFormat; + public ApiClient setSqlDateFormat(DateFormat dateFormat) { + this.json.setSqlDateFormat(dateFormat); return this; } - /** - * Whether to allow various ISO 8601 datetime formats when parsing a datetime string. - * @see #parseDatetime(String) - * @return True if lenientDatetimeFormat flag is set to true - */ - public boolean isLenientDatetimeFormat() { - return lenientDatetimeFormat; - } - - public ApiClient setLenientDatetimeFormat(boolean lenientDatetimeFormat) { - this.lenientDatetimeFormat = lenientDatetimeFormat; + public ApiClient setDateTimeFormat(DateTimeFormatter dateFormat) { + this.json.setDateTimeFormat(dateFormat); return this; } - /** - * Parse the given date string into Date object. - * The default dateFormat supports these ISO 8601 date formats: - * 2015-08-16 - * 2015-8-16 - * @param str String to be parsed - * @return Date - */ - public Date parseDate(String str) { - if (str == null) - return null; - try { - return dateFormat.parse(str); - } catch (ParseException e) { - throw new RuntimeException(e); - } + public ApiClient setLocalDateFormat(DateTimeFormatter dateFormat) { + this.json.setLocalDateFormat(dateFormat); + return this; } - /** - * Parse the given datetime string into Date object. - * When lenientDatetimeFormat is enabled, the following ISO 8601 datetime formats are supported: - * 2015-08-16T08:20:05Z - * 2015-8-16T8:20:05Z - * 2015-08-16T08:20:05+00:00 - * 2015-08-16T08:20:05+0000 - * 2015-08-16T08:20:05.376Z - * 2015-08-16T08:20:05.376+00:00 - * 2015-08-16T08:20:05.376+00 - * Note: The 3-digit milli-seconds is optional. Time zone is required and can be in one of - * these formats: - * Z (same with +0000) - * +08:00 (same with +0800) - * -02 (same with -0200) - * -0200 - * @see ISO 8601 - * @param str Date time string to be parsed - * @return Date representation of the string - */ - public Date parseDatetime(String str) { - if (str == null) - return null; - - DateFormat format; - if (lenientDatetimeFormat) { - /* - * When lenientDatetimeFormat is enabled, normalize the date string - * into LENIENT_DATETIME_FORMAT to support various formats - * defined by ISO 8601. - */ - // normalize time zone - // trailing "Z": 2015-08-16T08:20:05Z => 2015-08-16T08:20:05+0000 - str = str.replaceAll("[zZ]\\z", "+0000"); - // remove colon in time zone: 2015-08-16T08:20:05+00:00 => 2015-08-16T08:20:05+0000 - str = str.replaceAll("([+-]\\d{2}):(\\d{2})\\z", "$1$2"); - // expand time zone: 2015-08-16T08:20:05+00 => 2015-08-16T08:20:05+0000 - str = str.replaceAll("([+-]\\d{2})\\z", "$100"); - // add milliseconds when missing - // 2015-08-16T08:20:05+0000 => 2015-08-16T08:20:05.000+0000 - str = str.replaceAll("(:\\d{1,2})([+-]\\d{4})\\z", "$1.000$2"); - format = new SimpleDateFormat(LENIENT_DATETIME_FORMAT); - } else { - format = this.datetimeFormat; - } - - try { - return format.parse(str); - } catch (ParseException e) { - throw new RuntimeException(e); - } - } - - /* - * Parse date or date time in string format into Date object. - * - * @param str Date time string to be parsed - * @return Date representation of the string - */ - public Date parseDateOrDatetime(String str) { - if (str == null) - return null; - else if (str.length() <= dateLength) - return parseDate(str); - else - return parseDatetime(str); - } - - /** - * Format the given Date object into string (Date format). - * - * @param date Date object - * @return Formatted date in string representation - */ - public String formatDate(Date date) { - return dateFormat.format(date); - } - - /** - * Format the given Date object into string (Datetime format). - * - * @param date Date object - * @return Formatted datetime in string representation - */ - public String formatDatetime(Date date) { - return datetimeFormat.format(date); + public ApiClient setLenientOnJson(boolean lenientOnJson) { + this.json.setLenientOnJson(lenientOnJson); + return this; } /** @@ -541,26 +346,6 @@ public class ApiClient { return this; } - /** - * @see setLenient - * - * @return True if lenientOnJson is enabled, false otherwise. - */ - public boolean isLenientOnJson() { - return lenientOnJson; - } - - /** - * Set LenientOnJson - * - * @param lenient True to enable lenientOnJson - * @return ApiClient - */ - public ApiClient setLenientOnJson(boolean lenient) { - this.lenientOnJson = lenient; - return this; - } - /** * Check that whether debugging is enabled for this API client. * @@ -644,8 +429,10 @@ public class ApiClient { public String parameterToString(Object param) { if (param == null) { return ""; - } else if (param instanceof Date) { - return formatDatetime((Date) param); + } else if (param instanceof Date || param instanceof DateTime || param instanceof LocalDate) { + //Serialize to json string and remove the " enclosing characters + String jsonStr = json.serialize(param); + return jsonStr.substring(1, jsonStr.length() - 1); } else if (param instanceof Collection) { StringBuilder b = new StringBuilder(); for (Object o : (Collection)param) { @@ -1235,31 +1022,6 @@ public class ApiClient { } } - /** - * Initialize datetime format according to the current environment, e.g. Java 1.7 and Android. - */ - private void initDatetimeFormat() { - String formatWithTimeZone = null; - if (IS_ANDROID) { - if (ANDROID_SDK_VERSION >= 18) { - // The time zone format "ZZZZZ" is available since Android 4.3 (SDK version 18) - formatWithTimeZone = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"; - } - } else if (JAVA_VERSION >= 1.7) { - // The time zone format "XXX" is available since Java 1.7 - formatWithTimeZone = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX"; - } - if (formatWithTimeZone != null) { - this.datetimeFormat = new SimpleDateFormat(formatWithTimeZone); - // NOTE: Use the system's default time zone (mainly for datetime formatting). - } else { - // Use a common format that works across all systems. - this.datetimeFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); - // Always use the UTC time zone as we are using a constant trailing "Z" here. - this.datetimeFormat.setTimeZone(TimeZone.getTimeZone("UTC")); - } - } - /** * Apply SSL related settings to httpClient according to the current values of * verifyingSsl and sslCaCert. diff --git a/samples/client/petstore/java/okhttp-gson/src/main/java/io/swagger/client/JSON.java b/samples/client/petstore/java/okhttp-gson/src/main/java/io/swagger/client/JSON.java index a734bec47f1b..64c68da1f251 100644 --- a/samples/client/petstore/java/okhttp-gson/src/main/java/io/swagger/client/JSON.java +++ b/samples/client/petstore/java/okhttp-gson/src/main/java/io/swagger/client/JSON.java @@ -27,43 +27,38 @@ package io.swagger.client; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonNull; import com.google.gson.JsonParseException; -import com.google.gson.JsonPrimitive; -import com.google.gson.JsonSerializationContext; -import com.google.gson.JsonSerializer; import com.google.gson.TypeAdapter; +import com.google.gson.internal.bind.util.ISO8601Utils; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; - -import java.io.IOException; -import java.io.StringReader; -import java.lang.reflect.Type; -import java.util.Date; - import org.joda.time.DateTime; import org.joda.time.LocalDate; import org.joda.time.format.DateTimeFormatter; import org.joda.time.format.ISODateTimeFormat; -public class JSON { - private ApiClient apiClient; - private Gson gson; +import java.io.IOException; +import java.io.StringReader; +import java.lang.reflect.Type; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.ParsePosition; +import java.util.Date; - /** - * JSON constructor. - * - * @param apiClient An instance of ApiClient - */ - public JSON(ApiClient apiClient) { - this.apiClient = apiClient; +public class JSON { + private Gson gson; + private boolean isLenientOnJson = false; + private DateTypeAdapter dateTypeAdapter = new DateTypeAdapter(); + private SqlDateTypeAdapter sqlDateTypeAdapter = new SqlDateTypeAdapter(); + private DateTimeTypeAdapter dateTimeTypeAdapter = new DateTimeTypeAdapter(); + private LocalDateTypeAdapter localDateTypeAdapter = new LocalDateTypeAdapter(); + + public JSON() { gson = new GsonBuilder() - .registerTypeAdapter(Date.class, new DateAdapter(apiClient)) - .registerTypeAdapter(DateTime.class, new DateTimeTypeAdapter()) - .registerTypeAdapter(LocalDate.class, new LocalDateTypeAdapter()) + .registerTypeAdapter(Date.class, dateTypeAdapter) + .registerTypeAdapter(java.sql.Date.class, sqlDateTypeAdapter) + .registerTypeAdapter(DateTime.class, dateTimeTypeAdapter) + .registerTypeAdapter(LocalDate.class, localDateTypeAdapter) .create(); } @@ -81,8 +76,14 @@ public class JSON { * * @param gson Gson */ - public void setGson(Gson gson) { + public JSON setGson(Gson gson) { this.gson = gson; + return this; + } + + public JSON setLenientOnJson(boolean lenientOnJson) { + isLenientOnJson = lenientOnJson; + return this; } /** @@ -98,15 +99,15 @@ public class JSON { /** * Deserialize the given JSON string to Java object. * - * @param Type - * @param body The JSON string + * @param Type + * @param body The JSON string * @param returnType The type to deserialize into * @return The deserialized Java object */ @SuppressWarnings("unchecked") public T deserialize(String body, Type returnType) { try { - if (apiClient.isLenientOnJson()) { + if (isLenientOnJson) { JsonReader jsonReader = new JsonReader(new StringReader(body)); // see https://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/stream/JsonReader.html#setLenient(boolean) jsonReader.setLenient(true); @@ -116,121 +117,226 @@ public class JSON { } } catch (JsonParseException e) { // Fallback processing when failed to parse JSON form response body: - // return the response body string directly for the String return type; - // parse response body into date or datetime for the Date return type. + // return the response body string directly for the String return type; if (returnType.equals(String.class)) return (T) body; - else if (returnType.equals(Date.class)) - return (T) apiClient.parseDateOrDatetime(body); - else throw(e); - } - } -} - -class DateAdapter implements JsonSerializer, JsonDeserializer { - private final ApiClient apiClient; - - /** - * Constructor for DateAdapter - * - * @param apiClient Api client - */ - public DateAdapter(ApiClient apiClient) { - super(); - this.apiClient = apiClient; - } - - /** - * Serialize - * - * @param src Date - * @param typeOfSrc Type - * @param context Json Serialization Context - * @return Json Element - */ - @Override - public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) { - if (src == null) { - return JsonNull.INSTANCE; - } else { - return new JsonPrimitive(apiClient.formatDatetime(src)); + else throw (e); } } /** - * Deserialize - * - * @param json Json element - * @param date Type - * @param context Json Serialization Context - * @return Date - * @throws JsonParseException if fail to parse + * Gson TypeAdapter for Joda DateTime type */ - @Override - public Date deserialize(JsonElement json, Type date, JsonDeserializationContext context) throws JsonParseException { - String str = json.getAsJsonPrimitive().getAsString(); - try { - return apiClient.parseDateOrDatetime(str); - } catch (RuntimeException e) { - throw new JsonParseException(e); - } - } -} - -/** - * Gson TypeAdapter for Joda DateTime type - */ -class DateTimeTypeAdapter extends TypeAdapter { - - private final DateTimeFormatter formatter = ISODateTimeFormat.dateTime(); - - @Override - public void write(JsonWriter out, DateTime date) throws IOException { - if (date == null) { - out.nullValue(); - } else { - out.value(formatter.print(date)); - } - } - - @Override - public DateTime read(JsonReader in) throws IOException { - switch (in.peek()) { - case NULL: - in.nextNull(); - return null; - default: - String date = in.nextString(); - return formatter.parseDateTime(date); - } - } -} - -/** - * Gson TypeAdapter for Joda LocalDate type - */ -class LocalDateTypeAdapter extends TypeAdapter { - - private final DateTimeFormatter formatter = ISODateTimeFormat.date(); - - @Override - public void write(JsonWriter out, LocalDate date) throws IOException { - if (date == null) { - out.nullValue(); - } else { - out.value(formatter.print(date)); - } - } - - @Override - public LocalDate read(JsonReader in) throws IOException { - switch (in.peek()) { - case NULL: - in.nextNull(); - return null; - default: - String date = in.nextString(); - return formatter.parseLocalDate(date); + public static class DateTimeTypeAdapter extends TypeAdapter { + + private DateTimeFormatter formatter; + + public DateTimeTypeAdapter() { + this(ISODateTimeFormat.dateTime().withOffsetParsed()); + } + + public DateTimeTypeAdapter(DateTimeFormatter formatter) { + this.formatter = formatter; + } + + public void setFormat(DateTimeFormatter dateFormat) { + this.formatter = dateFormat; + } + + @Override + public void write(JsonWriter out, DateTime date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + out.value(formatter.print(date)); + } + } + + @Override + public DateTime read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + return formatter.parseDateTime(date); + } } } + + /** + * Gson TypeAdapter for Joda LocalDate type + */ + public class LocalDateTypeAdapter extends TypeAdapter { + + private DateTimeFormatter formatter; + + public LocalDateTypeAdapter() { + this(ISODateTimeFormat.date()); + } + + public LocalDateTypeAdapter(DateTimeFormatter formatter) { + this.formatter = formatter; + } + + public void setFormat(DateTimeFormatter dateFormat) { + this.formatter = dateFormat; + } + + @Override + public void write(JsonWriter out, LocalDate date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + out.value(formatter.print(date)); + } + } + + @Override + public LocalDate read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + return formatter.parseLocalDate(date); + } + } + } + + public JSON setDateTimeFormat(DateTimeFormatter dateFormat) { + dateTimeTypeAdapter.setFormat(dateFormat); + return this; + } + + public JSON setLocalDateFormat(DateTimeFormatter dateFormat) { + localDateTypeAdapter.setFormat(dateFormat); + return this; + } + + /** + * Gson TypeAdapter for java.sql.Date type + * If the dateFormat is null, a simple "yyyy-MM-dd" format will be used + * (more efficient than SimpleDateFormat). + */ + public static class SqlDateTypeAdapter extends TypeAdapter { + + private DateFormat dateFormat; + + public SqlDateTypeAdapter() { + } + + public SqlDateTypeAdapter(DateFormat dateFormat) { + this.dateFormat = dateFormat; + } + + public void setFormat(DateFormat dateFormat) { + this.dateFormat = dateFormat; + } + + @Override + public void write(JsonWriter out, java.sql.Date date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + String value; + if (dateFormat != null) { + value = dateFormat.format(date); + } else { + value = date.toString(); + } + out.value(value); + } + } + + @Override + public java.sql.Date read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + try { + if (dateFormat != null) { + return new java.sql.Date(dateFormat.parse(date).getTime()); + } + return new java.sql.Date(ISO8601Utils.parse(date, new ParsePosition(0)).getTime()); + } catch (ParseException e) { + throw new JsonParseException(e); + } + } + } + } + + /** + * Gson TypeAdapter for java.util.Date type + * If the dateFormat is null, ISO8601Utils will be used. + */ + public static class DateTypeAdapter extends TypeAdapter { + + private DateFormat dateFormat; + + public DateTypeAdapter() { + } + + public DateTypeAdapter(DateFormat dateFormat) { + this.dateFormat = dateFormat; + } + + public void setFormat(DateFormat dateFormat) { + this.dateFormat = dateFormat; + } + + @Override + public void write(JsonWriter out, Date date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + String value; + if (dateFormat != null) { + value = dateFormat.format(date); + } else { + value = ISO8601Utils.format(date, true); + } + out.value(value); + } + } + + @Override + public Date read(JsonReader in) throws IOException { + try { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + try { + if (dateFormat != null) { + return dateFormat.parse(date); + } + return ISO8601Utils.parse(date, new ParsePosition(0)); + } catch (ParseException e) { + throw new JsonParseException(e); + } + } + } catch (IllegalArgumentException e) { + throw new JsonParseException(e); + } + } + } + + public JSON setDateFormat(DateFormat dateFormat) { + dateTypeAdapter.setFormat(dateFormat); + return this; + } + + public JSON setSqlDateFormat(DateFormat dateFormat) { + sqlDateTypeAdapter.setFormat(dateFormat); + return this; + } + } diff --git a/samples/client/petstore/java/okhttp-gson/src/test/java/io/swagger/client/ApiClientTest.java b/samples/client/petstore/java/okhttp-gson/src/test/java/io/swagger/client/ApiClientTest.java index 5345e2a1646e..df6cff4ecb79 100644 --- a/samples/client/petstore/java/okhttp-gson/src/test/java/io/swagger/client/ApiClientTest.java +++ b/samples/client/petstore/java/okhttp-gson/src/test/java/io/swagger/client/ApiClientTest.java @@ -12,69 +12,13 @@ import static org.junit.Assert.*; public class ApiClientTest { - ApiClient apiClient = null; + ApiClient apiClient; + JSON json; @Before public void setup() { apiClient = new ApiClient(); - } - - @Test - public void testParseAndFormatDatetime() { - // default datetime format with UTC time zone - apiClient.getDatetimeFormat().setTimeZone(TimeZone.getTimeZone("UTC")); - String dateStr = "2015-11-07T03:49:09.356Z"; - assertTrue(apiClient.isLenientDatetimeFormat()); - assertEquals(dateStr, apiClient.formatDatetime(apiClient.parseDatetime("2015-11-07T03:49:09.356+00:00"))); - assertEquals(dateStr, apiClient.formatDatetime(apiClient.parseDatetime("2015-11-07T05:49:09.356+02:00"))); - assertEquals(dateStr, apiClient.formatDatetime(apiClient.parseDatetime("2015-11-07T02:49:09.356-01:00"))); - // support various cases - assertEquals(dateStr, apiClient.formatDatetime(apiClient.parseDatetime("2015-11-07T03:49:09.356Z"))); - assertEquals(dateStr, apiClient.formatDatetime(apiClient.parseDatetime("2015-11-07T03:49:09.356+00"))); - assertEquals(dateStr, apiClient.formatDatetime(apiClient.parseDatetime("2015-11-07T02:49:09.356-0100"))); - dateStr = "2015-11-07T03:49:09.000Z"; - assertEquals(dateStr, apiClient.formatDatetime(apiClient.parseDatetime("2015-11-07T05:49:09+02"))); - - // custom datetime format: without milli-seconds, custom time zone - DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX"); - format.setTimeZone(TimeZone.getTimeZone("GMT+10")); - apiClient.setDatetimeFormat(format); - // disable support of various datetime format - apiClient.setLenientDatetimeFormat(false); - dateStr = "2015-11-07T13:49:09+10:00"; - assertEquals(dateStr, apiClient.formatDatetime(apiClient.parseDatetime("2015-11-07T03:49:09+00:00"))); - assertEquals(dateStr, apiClient.formatDatetime(apiClient.parseDatetime("2015-11-07T03:49:09Z"))); - assertEquals(dateStr, apiClient.formatDatetime(apiClient.parseDatetime("2015-11-07T00:49:09-03:00"))); - - try { - // invalid time zone format - apiClient.parseDatetime("2015-11-07T03:49:09+00"); - fail("parseDatetime should fail"); - } catch (RuntimeException e) { - // OK - } - try { - // unexpected miliseconds - apiClient.parseDatetime("2015-11-07T03:49:09.000Z"); - fail("parseDatetime should fail"); - } catch (RuntimeException e) { - // OK - } - } - - @Test - public void testParseAndFormatDate() { - // default date format - String dateStr = "2015-11-07"; - assertEquals(dateStr, apiClient.formatDate(apiClient.parseDatetime("2015-11-07T03:49:09.356+00:00"))); - assertEquals(dateStr, apiClient.formatDate(apiClient.parseDate("2015-11-07"))); - - // custom date format: without day - DateFormat format = new SimpleDateFormat("yyyy-MM"); - apiClient.setDateFormat(format); - dateStr = "2015-11"; - assertEquals(dateStr, apiClient.formatDate(apiClient.parseDatetime("2015-11-07T03:49:09Z"))); - assertEquals(dateStr, apiClient.formatDate(apiClient.parseDate("2015-11"))); + json = apiClient.getJSON(); } @Test diff --git a/samples/client/petstore/java/okhttp-gson/src/test/java/io/swagger/client/JSONTest.java b/samples/client/petstore/java/okhttp-gson/src/test/java/io/swagger/client/JSONTest.java index 8dab64b289e2..13ad996920a5 100644 --- a/samples/client/petstore/java/okhttp-gson/src/test/java/io/swagger/client/JSONTest.java +++ b/samples/client/petstore/java/okhttp-gson/src/test/java/io/swagger/client/JSONTest.java @@ -6,8 +6,16 @@ import io.swagger.client.model.Order; import java.lang.Exception; import java.lang.reflect.Type; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.TimeZone; +import org.joda.time.DateTime; import org.joda.time.DateTimeZone; +import org.joda.time.LocalDate; import org.joda.time.format.DateTimeFormatter; import org.joda.time.format.ISODateTimeFormat; import org.junit.*; @@ -21,10 +29,99 @@ public class JSONTest { @Before public void setup() { apiClient = new ApiClient(); - json = new JSON(apiClient); + json = apiClient.getJSON(); order = new Order(); } + @Test + public void testSqlDateTypeAdapter() { + final String str = "\"2015-11-07\""; + final java.sql.Date date = java.sql.Date.valueOf("2015-11-07"); + + assertEquals(str, json.serialize(date)); + assertEquals(json.deserialize(str, java.sql.Date.class), date); + assertEquals(json.deserialize("\"2015-11-07T03:49:09.356+00:00\"", java.sql.Date.class).toString(), date.toString()); + + // custom date format: without day + DateFormat format = new SimpleDateFormat("yyyy-MM"); + apiClient.setSqlDateFormat(format); + String dateStr = "\"2015-11\""; + assertEquals(dateStr, json.serialize(json.deserialize("\"2015-11-07T03:49:09Z\"", java.sql.Date.class))); + assertEquals(dateStr, json.serialize(json.deserialize("\"2015-11\"", java.sql.Date.class))); + } + + @Test + public void testDateTypeAdapter() { + Calendar cal = new GregorianCalendar(2015, 10, 7, 3, 49, 9); + cal.setTimeZone(TimeZone.getTimeZone("UTC")); + + assertEquals(json.deserialize("\"2015-11-07T05:49:09+02\"", Date.class), cal.getTime()); + + cal.set(Calendar.MILLISECOND, 300); + assertEquals(json.deserialize("\"2015-11-07T03:49:09.3Z\"", Date.class), cal.getTime()); + + cal.set(Calendar.MILLISECOND, 356); + Date date = cal.getTime(); + + final String utcDate = "\"2015-11-07T03:49:09.356Z\""; + assertEquals(json.deserialize(utcDate, Date.class), date); + assertEquals(json.deserialize("\"2015-11-07T03:49:09.356+00:00\"", Date.class), date); + assertEquals(json.deserialize("\"2015-11-07T05:49:09.356+02:00\"", Date.class), date); + assertEquals(json.deserialize("\"2015-11-07T02:49:09.356-01:00\"", Date.class), date); + assertEquals(json.deserialize("\"2015-11-07T03:49:09.356Z\"", Date.class), date); + assertEquals(json.deserialize("\"2015-11-07T03:49:09.356+00\"", Date.class), date); + assertEquals(json.deserialize("\"2015-11-07T02:49:09.356-0100\"", Date.class), date); + assertEquals(json.deserialize("\"2015-11-07T03:49:09.356456789Z\"", Date.class), date); + + assertEquals(utcDate, json.serialize(date)); + + // custom datetime format: without milli-seconds, custom time zone + DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX"); + format.setTimeZone(TimeZone.getTimeZone("GMT+10")); + apiClient.setDateFormat(format); + + String dateStr = "\"2015-11-07T13:49:09+10:00\""; + assertEquals(dateStr, json.serialize(json.deserialize("\"2015-11-07T03:49:09+00:00\"", Date.class))); + assertEquals(dateStr, json.serialize(json.deserialize("\"2015-11-07T03:49:09Z\"", Date.class))); + assertEquals(dateStr, json.serialize(json.deserialize("\"2015-11-07T00:49:09-03:00\"", Date.class))); + + try { + // invalid time zone format + json.deserialize("\"2015-11-07T03:49:09+00\"", Date.class); + fail("json parsing should fail"); + } catch (RuntimeException e) { + // OK + } + try { + // unexpected miliseconds + json.deserialize("\"2015-11-07T03:49:09.000Z\"", Date.class); + fail("json parsing should fail"); + } catch (RuntimeException e) { + // OK + } + + } + + @Test + public void testDateTimeTypeAdapter() { + final String str = "\"2016-09-09T08:02:03.123-03:00\""; + DateTime date = new DateTime(2016, 9, 9, 8, 2, 3, 123, DateTimeZone.forID("Etc/GMT+3")); + + assertEquals(str, json.serialize(date)); + //Use toString() instead of isEqual to verify that the offset is preserved + assertEquals(json.deserialize(str, DateTime.class).toString(), date.toString()); + } + + @Test + public void testLocalDateTypeAdapter() { + final String str = "\"2016-09-09\""; + final LocalDate date = new LocalDate(2016, 9, 9); + + assertEquals(str, json.serialize(date)); + assertEquals(json.deserialize(str, LocalDate.class), date); + } + + @Test public void testDefaultDate() throws Exception { final DateTimeFormatter datetimeFormat = ISODateTimeFormat.dateTime().withZone(DateTimeZone.UTC); diff --git a/samples/client/petstore/java/okhttp-gson/src/test/java/io/swagger/client/api/PetApiTest.java b/samples/client/petstore/java/okhttp-gson/src/test/java/io/swagger/client/api/PetApiTest.java index 8bfb76050930..497c31d6b1bf 100644 --- a/samples/client/petstore/java/okhttp-gson/src/test/java/io/swagger/client/api/PetApiTest.java +++ b/samples/client/petstore/java/okhttp-gson/src/test/java/io/swagger/client/api/PetApiTest.java @@ -153,7 +153,7 @@ public class PetApiTest { // test getting a nonexistent pet result.clear(); - api.getPetByIdAsync(new Long(-10000), new ApiCallback() { + api.getPetByIdAsync(-10000L, new ApiCallback() { @Override public void onFailure(ApiException e, int statusCode, Map> responseHeaders) { result.put("exception", e); @@ -174,8 +174,6 @@ public class PetApiTest { //empty } }); - // the API call should be executed asynchronously, so result should be empty at the moment - assertTrue(result.isEmpty()); // wait for the asynchronous call to finish (at most 10 seconds) tryCount = 1; @@ -254,7 +252,7 @@ public class PetApiTest { api.updatePet(pet); - List pets = api.findPetsByStatus(Arrays.asList(new String[]{"pending"})); + List pets = api.findPetsByStatus(Arrays.asList("pending")); assertNotNull(pets); boolean found = false; @@ -284,7 +282,7 @@ public class PetApiTest { api.updatePet(pet); - List pets = api.findPetsByTags(Arrays.asList(new String[]{"friendly"})); + List pets = api.findPetsByTags(Arrays.asList("friendly")); assertNotNull(pets); boolean found = false; @@ -353,7 +351,7 @@ public class PetApiTest { assertTrue(pet1.hashCode() == pet1.hashCode()); pet2.setName("really-happy"); - pet2.setPhotoUrls(Arrays.asList(new String[]{"http://foo.bar.com/1", "http://foo.bar.com/2"})); + pet2.setPhotoUrls(Arrays.asList("http://foo.bar.com/1", "http://foo.bar.com/2")); assertFalse(pet1.equals(pet2)); assertFalse(pet2.equals(pet1)); assertFalse(pet1.hashCode() == (pet2.hashCode())); @@ -361,7 +359,7 @@ public class PetApiTest { assertTrue(pet2.hashCode() == pet2.hashCode()); pet1.setName("really-happy"); - pet1.setPhotoUrls(Arrays.asList(new String[]{"http://foo.bar.com/1", "http://foo.bar.com/2"})); + pet1.setPhotoUrls(Arrays.asList("http://foo.bar.com/1", "http://foo.bar.com/2")); assertTrue(pet1.equals(pet2)); assertTrue(pet2.equals(pet1)); assertTrue(pet1.hashCode() == pet2.hashCode()); @@ -379,7 +377,7 @@ public class PetApiTest { pet.setCategory(category); pet.setStatus(Pet.StatusEnum.AVAILABLE); - List photos = Arrays.asList(new String[]{"http://foo.bar.com/1", "http://foo.bar.com/2"}); + List photos = Arrays.asList("http://foo.bar.com/1", "http://foo.bar.com/2"); pet.setPhotoUrls(photos); return pet; diff --git a/samples/client/petstore/java/okhttp-gson/src/test/java/io/swagger/client/api/StoreApiTest.java b/samples/client/petstore/java/okhttp-gson/src/test/java/io/swagger/client/api/StoreApiTest.java index 0e18ce8e07a7..84a20f33392f 100644 --- a/samples/client/petstore/java/okhttp-gson/src/test/java/io/swagger/client/api/StoreApiTest.java +++ b/samples/client/petstore/java/okhttp-gson/src/test/java/io/swagger/client/api/StoreApiTest.java @@ -22,12 +22,6 @@ public class StoreApiTest { // setup authentication ApiKeyAuth apiKeyAuth = (ApiKeyAuth) api.getApiClient().getAuthentication("api_key"); apiKeyAuth.setApiKey("special-key"); - // set custom date format that is used by the petstore server - // Note: it would still work without this setting as okhttp-gson Java client supports - // various date formats by default (with lenientDatetimeFormat enabled), including - // the one used by petstore server - api.getApiClient().setDatetimeFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")); - api.getApiClient().setLenientDatetimeFormat(false); } @Test @@ -84,8 +78,8 @@ public class StoreApiTest { private Order createOrder() { Order order = new Order(); - order.setPetId(new Long(200)); - order.setQuantity(new Integer(13)); + order.setPetId(200L); + order.setQuantity(13); order.setShipDate(org.joda.time.DateTime.now()); order.setStatus(Order.StatusEnum.PLACED); order.setComplete(true);