Repository: eclipse-vertx/vert.x

Problem statement:
WebSocket server connection close timeout
When a WebSocket is closed by the server, it sends a close frame and  waits until it receives the echo close frame to close the TCP connection. We should have a timeout to close the TCP connection to prevent a server from keeping a WebSocket without receiving a close frame.

NOTE: this will not happen when an idle timeout is configured on the server which is a recommended practice.



Hints:

Patch:
diff --git a/src/main/generated/io/vertx/core/DeploymentOptionsConverter.java b/src/main/generated/io/vertx/core/DeploymentOptionsConverter.java
new file mode 100644
--- /dev/null
+++ b/src/main/generated/io/vertx/core/DeploymentOptionsConverter.java
@@ -0,0 +1,125 @@
+package io.vertx.core;
+
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.json.JsonArray;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Converter for {@link io.vertx.core.DeploymentOptions}.
+ * NOTE: This class has been automatically generated from the {@link io.vertx.core.DeploymentOptions} original class using Vert.x codegen.
+ */
+ class DeploymentOptionsConverter {
+
+   static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, DeploymentOptions obj) {
+    for (java.util.Map.Entry<String, Object> member : json) {
+      switch (member.getKey()) {
+        case "config":
+          if (member.getValue() instanceof JsonObject) {
+            obj.setConfig(((JsonObject)member.getValue()).copy());
+          }
+          break;
+        case "extraClasspath":
+          if (member.getValue() instanceof JsonArray) {
+            java.util.ArrayList<java.lang.String> list =  new java.util.ArrayList<>();
+            ((Iterable<Object>)member.getValue()).forEach( item -> {
+              if (item instanceof String)
+                list.add((String)item);
+            });
+            obj.setExtraClasspath(list);
+          }
+          break;
+        case "ha":
+          if (member.getValue() instanceof Boolean) {
+            obj.setHa((Boolean)member.getValue());
+          }
+          break;
+        case "instances":
+          if (member.getValue() instanceof Number) {
+            obj.setInstances(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "isolatedClasses":
+          if (member.getValue() instanceof JsonArray) {
+            java.util.ArrayList<java.lang.String> list =  new java.util.ArrayList<>();
+            ((Iterable<Object>)member.getValue()).forEach( item -> {
+              if (item instanceof String)
+                list.add((String)item);
+            });
+            obj.setIsolatedClasses(list);
+          }
+          break;
+        case "isolationGroup":
+          if (member.getValue() instanceof String) {
+            obj.setIsolationGroup((String)member.getValue());
+          }
+          break;
+        case "maxWorkerExecuteTime":
+          if (member.getValue() instanceof Number) {
+            obj.setMaxWorkerExecuteTime(((Number)member.getValue()).longValue());
+          }
+          break;
+        case "maxWorkerExecuteTimeUnit":
+          if (member.getValue() instanceof String) {
+            obj.setMaxWorkerExecuteTimeUnit(java.util.concurrent.TimeUnit.valueOf((String)member.getValue()));
+          }
+          break;
+        case "multiThreaded":
+          if (member.getValue() instanceof Boolean) {
+            obj.setMultiThreaded((Boolean)member.getValue());
+          }
+          break;
+        case "worker":
+          if (member.getValue() instanceof Boolean) {
+            obj.setWorker((Boolean)member.getValue());
+          }
+          break;
+        case "workerPoolName":
+          if (member.getValue() instanceof String) {
+            obj.setWorkerPoolName((String)member.getValue());
+          }
+          break;
+        case "workerPoolSize":
+          if (member.getValue() instanceof Number) {
+            obj.setWorkerPoolSize(((Number)member.getValue()).intValue());
+          }
+          break;
+      }
+    }
+  }
+
+   static void toJson(DeploymentOptions obj, JsonObject json) {
+    toJson(obj, json.getMap());
+  }
+
+   static void toJson(DeploymentOptions obj, java.util.Map<String, Object> json) {
+    if (obj.getConfig() != null) {
+      json.put("config", obj.getConfig());
+    }
+    if (obj.getExtraClasspath() != null) {
+      JsonArray array = new JsonArray();
+      obj.getExtraClasspath().forEach(item -> array.add(item));
+      json.put("extraClasspath", array);
+    }
+    json.put("ha", obj.isHa());
+    json.put("instances", obj.getInstances());
+    if (obj.getIsolatedClasses() != null) {
+      JsonArray array = new JsonArray();
+      obj.getIsolatedClasses().forEach(item -> array.add(item));
+      json.put("isolatedClasses", array);
+    }
+    if (obj.getIsolationGroup() != null) {
+      json.put("isolationGroup", obj.getIsolationGroup());
+    }
+    json.put("maxWorkerExecuteTime", obj.getMaxWorkerExecuteTime());
+    if (obj.getMaxWorkerExecuteTimeUnit() != null) {
+      json.put("maxWorkerExecuteTimeUnit", obj.getMaxWorkerExecuteTimeUnit().name());
+    }
+    json.put("multiThreaded", obj.isMultiThreaded());
+    json.put("worker", obj.isWorker());
+    if (obj.getWorkerPoolName() != null) {
+      json.put("workerPoolName", obj.getWorkerPoolName());
+    }
+    json.put("workerPoolSize", obj.getWorkerPoolSize());
+  }
+}
diff --git a/src/main/generated/io/vertx/core/VertxOptionsConverter.java b/src/main/generated/io/vertx/core/VertxOptionsConverter.java
new file mode 100644
--- /dev/null
+++ b/src/main/generated/io/vertx/core/VertxOptionsConverter.java
@@ -0,0 +1,211 @@
+package io.vertx.core;
+
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.json.JsonArray;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Converter for {@link io.vertx.core.VertxOptions}.
+ * NOTE: This class has been automatically generated from the {@link io.vertx.core.VertxOptions} original class using Vert.x codegen.
+ */
+ class VertxOptionsConverter {
+
+   static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, VertxOptions obj) {
+    for (java.util.Map.Entry<String, Object> member : json) {
+      switch (member.getKey()) {
+        case "addressResolverOptions":
+          if (member.getValue() instanceof JsonObject) {
+            obj.setAddressResolverOptions(new io.vertx.core.dns.AddressResolverOptions((JsonObject)member.getValue()));
+          }
+          break;
+        case "blockedThreadCheckInterval":
+          if (member.getValue() instanceof Number) {
+            obj.setBlockedThreadCheckInterval(((Number)member.getValue()).longValue());
+          }
+          break;
+        case "blockedThreadCheckIntervalUnit":
+          if (member.getValue() instanceof String) {
+            obj.setBlockedThreadCheckIntervalUnit(java.util.concurrent.TimeUnit.valueOf((String)member.getValue()));
+          }
+          break;
+        case "clusterHost":
+          if (member.getValue() instanceof String) {
+            obj.setClusterHost((String)member.getValue());
+          }
+          break;
+        case "clusterPingInterval":
+          if (member.getValue() instanceof Number) {
+            obj.setClusterPingInterval(((Number)member.getValue()).longValue());
+          }
+          break;
+        case "clusterPingReplyInterval":
+          if (member.getValue() instanceof Number) {
+            obj.setClusterPingReplyInterval(((Number)member.getValue()).longValue());
+          }
+          break;
+        case "clusterPort":
+          if (member.getValue() instanceof Number) {
+            obj.setClusterPort(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "clusterPublicHost":
+          if (member.getValue() instanceof String) {
+            obj.setClusterPublicHost((String)member.getValue());
+          }
+          break;
+        case "clusterPublicPort":
+          if (member.getValue() instanceof Number) {
+            obj.setClusterPublicPort(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "clustered":
+          if (member.getValue() instanceof Boolean) {
+            obj.setClustered((Boolean)member.getValue());
+          }
+          break;
+        case "eventBusOptions":
+          if (member.getValue() instanceof JsonObject) {
+            obj.setEventBusOptions(new io.vertx.core.eventbus.EventBusOptions((JsonObject)member.getValue()));
+          }
+          break;
+        case "eventLoopPoolSize":
+          if (member.getValue() instanceof Number) {
+            obj.setEventLoopPoolSize(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "fileResolverCachingEnabled":
+          if (member.getValue() instanceof Boolean) {
+            obj.setFileResolverCachingEnabled((Boolean)member.getValue());
+          }
+          break;
+        case "fileSystemOptions":
+          if (member.getValue() instanceof JsonObject) {
+            obj.setFileSystemOptions(new io.vertx.core.file.FileSystemOptions((JsonObject)member.getValue()));
+          }
+          break;
+        case "haEnabled":
+          if (member.getValue() instanceof Boolean) {
+            obj.setHAEnabled((Boolean)member.getValue());
+          }
+          break;
+        case "haGroup":
+          if (member.getValue() instanceof String) {
+            obj.setHAGroup((String)member.getValue());
+          }
+          break;
+        case "internalBlockingPoolSize":
+          if (member.getValue() instanceof Number) {
+            obj.setInternalBlockingPoolSize(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "maxEventLoopExecuteTime":
+          if (member.getValue() instanceof Number) {
+            obj.setMaxEventLoopExecuteTime(((Number)member.getValue()).longValue());
+          }
+          break;
+        case "maxEventLoopExecuteTimeUnit":
+          if (member.getValue() instanceof String) {
+            obj.setMaxEventLoopExecuteTimeUnit(java.util.concurrent.TimeUnit.valueOf((String)member.getValue()));
+          }
+          break;
+        case "maxWorkerExecuteTime":
+          if (member.getValue() instanceof Number) {
+            obj.setMaxWorkerExecuteTime(((Number)member.getValue()).longValue());
+          }
+          break;
+        case "maxWorkerExecuteTimeUnit":
+          if (member.getValue() instanceof String) {
+            obj.setMaxWorkerExecuteTimeUnit(java.util.concurrent.TimeUnit.valueOf((String)member.getValue()));
+          }
+          break;
+        case "metricsOptions":
+          if (member.getValue() instanceof JsonObject) {
+            obj.setMetricsOptions(new io.vertx.core.metrics.MetricsOptions((JsonObject)member.getValue()));
+          }
+          break;
+        case "preferNativeTransport":
+          if (member.getValue() instanceof Boolean) {
+            obj.setPreferNativeTransport((Boolean)member.getValue());
+          }
+          break;
+        case "quorumSize":
+          if (member.getValue() instanceof Number) {
+            obj.setQuorumSize(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "warningExceptionTime":
+          if (member.getValue() instanceof Number) {
+            obj.setWarningExceptionTime(((Number)member.getValue()).longValue());
+          }
+          break;
+        case "warningExceptionTimeUnit":
+          if (member.getValue() instanceof String) {
+            obj.setWarningExceptionTimeUnit(java.util.concurrent.TimeUnit.valueOf((String)member.getValue()));
+          }
+          break;
+        case "workerPoolSize":
+          if (member.getValue() instanceof Number) {
+            obj.setWorkerPoolSize(((Number)member.getValue()).intValue());
+          }
+          break;
+      }
+    }
+  }
+
+   static void toJson(VertxOptions obj, JsonObject json) {
+    toJson(obj, json.getMap());
+  }
+
+   static void toJson(VertxOptions obj, java.util.Map<String, Object> json) {
+    if (obj.getAddressResolverOptions() != null) {
+      json.put("addressResolverOptions", obj.getAddressResolverOptions().toJson());
+    }
+    json.put("blockedThreadCheckInterval", obj.getBlockedThreadCheckInterval());
+    if (obj.getBlockedThreadCheckIntervalUnit() != null) {
+      json.put("blockedThreadCheckIntervalUnit", obj.getBlockedThreadCheckIntervalUnit().name());
+    }
+    if (obj.getClusterHost() != null) {
+      json.put("clusterHost", obj.getClusterHost());
+    }
+    json.put("clusterPingInterval", obj.getClusterPingInterval());
+    json.put("clusterPingReplyInterval", obj.getClusterPingReplyInterval());
+    json.put("clusterPort", obj.getClusterPort());
+    if (obj.getClusterPublicHost() != null) {
+      json.put("clusterPublicHost", obj.getClusterPublicHost());
+    }
+    json.put("clusterPublicPort", obj.getClusterPublicPort());
+    json.put("clustered", obj.isClustered());
+    if (obj.getEventBusOptions() != null) {
+      json.put("eventBusOptions", obj.getEventBusOptions().toJson());
+    }
+    json.put("eventLoopPoolSize", obj.getEventLoopPoolSize());
+    json.put("fileResolverCachingEnabled", obj.isFileResolverCachingEnabled());
+    if (obj.getFileSystemOptions() != null) {
+      json.put("fileSystemOptions", obj.getFileSystemOptions().toJson());
+    }
+    json.put("haEnabled", obj.isHAEnabled());
+    if (obj.getHAGroup() != null) {
+      json.put("haGroup", obj.getHAGroup());
+    }
+    json.put("internalBlockingPoolSize", obj.getInternalBlockingPoolSize());
+    json.put("maxEventLoopExecuteTime", obj.getMaxEventLoopExecuteTime());
+    if (obj.getMaxEventLoopExecuteTimeUnit() != null) {
+      json.put("maxEventLoopExecuteTimeUnit", obj.getMaxEventLoopExecuteTimeUnit().name());
+    }
+    json.put("maxWorkerExecuteTime", obj.getMaxWorkerExecuteTime());
+    if (obj.getMaxWorkerExecuteTimeUnit() != null) {
+      json.put("maxWorkerExecuteTimeUnit", obj.getMaxWorkerExecuteTimeUnit().name());
+    }
+    if (obj.getMetricsOptions() != null) {
+      json.put("metricsOptions", obj.getMetricsOptions().toJson());
+    }
+    json.put("preferNativeTransport", obj.getPreferNativeTransport());
+    json.put("quorumSize", obj.getQuorumSize());
+    json.put("warningExceptionTime", obj.getWarningExceptionTime());
+    if (obj.getWarningExceptionTimeUnit() != null) {
+      json.put("warningExceptionTimeUnit", obj.getWarningExceptionTimeUnit().name());
+    }
+    json.put("workerPoolSize", obj.getWorkerPoolSize());
+  }
+}
diff --git a/src/main/generated/io/vertx/core/cli/ArgumentConverter.java b/src/main/generated/io/vertx/core/cli/ArgumentConverter.java
new file mode 100644
--- /dev/null
+++ b/src/main/generated/io/vertx/core/cli/ArgumentConverter.java
@@ -0,0 +1,75 @@
+package io.vertx.core.cli;
+
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.json.JsonArray;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Converter for {@link io.vertx.core.cli.Argument}.
+ * NOTE: This class has been automatically generated from the {@link io.vertx.core.cli.Argument} original class using Vert.x codegen.
+ */
+ class ArgumentConverter {
+
+   static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, Argument obj) {
+    for (java.util.Map.Entry<String, Object> member : json) {
+      switch (member.getKey()) {
+        case "argName":
+          if (member.getValue() instanceof String) {
+            obj.setArgName((String)member.getValue());
+          }
+          break;
+        case "defaultValue":
+          if (member.getValue() instanceof String) {
+            obj.setDefaultValue((String)member.getValue());
+          }
+          break;
+        case "description":
+          if (member.getValue() instanceof String) {
+            obj.setDescription((String)member.getValue());
+          }
+          break;
+        case "hidden":
+          if (member.getValue() instanceof Boolean) {
+            obj.setHidden((Boolean)member.getValue());
+          }
+          break;
+        case "index":
+          if (member.getValue() instanceof Number) {
+            obj.setIndex(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "multiValued":
+          if (member.getValue() instanceof Boolean) {
+            obj.setMultiValued((Boolean)member.getValue());
+          }
+          break;
+        case "required":
+          if (member.getValue() instanceof Boolean) {
+            obj.setRequired((Boolean)member.getValue());
+          }
+          break;
+      }
+    }
+  }
+
+   static void toJson(Argument obj, JsonObject json) {
+    toJson(obj, json.getMap());
+  }
+
+   static void toJson(Argument obj, java.util.Map<String, Object> json) {
+    if (obj.getArgName() != null) {
+      json.put("argName", obj.getArgName());
+    }
+    if (obj.getDefaultValue() != null) {
+      json.put("defaultValue", obj.getDefaultValue());
+    }
+    if (obj.getDescription() != null) {
+      json.put("description", obj.getDescription());
+    }
+    json.put("hidden", obj.isHidden());
+    json.put("index", obj.getIndex());
+    json.put("multiValued", obj.isMultiValued());
+    json.put("required", obj.isRequired());
+  }
+}
diff --git a/src/main/generated/io/vertx/core/cli/OptionConverter.java b/src/main/generated/io/vertx/core/cli/OptionConverter.java
new file mode 100644
--- /dev/null
+++ b/src/main/generated/io/vertx/core/cli/OptionConverter.java
@@ -0,0 +1,123 @@
+package io.vertx.core.cli;
+
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.json.JsonArray;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Converter for {@link io.vertx.core.cli.Option}.
+ * NOTE: This class has been automatically generated from the {@link io.vertx.core.cli.Option} original class using Vert.x codegen.
+ */
+ class OptionConverter {
+
+   static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, Option obj) {
+    for (java.util.Map.Entry<String, Object> member : json) {
+      switch (member.getKey()) {
+        case "argName":
+          if (member.getValue() instanceof String) {
+            obj.setArgName((String)member.getValue());
+          }
+          break;
+        case "choices":
+          if (member.getValue() instanceof JsonArray) {
+            java.util.LinkedHashSet<java.lang.String> list =  new java.util.LinkedHashSet<>();
+            ((Iterable<Object>)member.getValue()).forEach( item -> {
+              if (item instanceof String)
+                list.add((String)item);
+            });
+            obj.setChoices(list);
+          }
+          break;
+        case "defaultValue":
+          if (member.getValue() instanceof String) {
+            obj.setDefaultValue((String)member.getValue());
+          }
+          break;
+        case "description":
+          if (member.getValue() instanceof String) {
+            obj.setDescription((String)member.getValue());
+          }
+          break;
+        case "flag":
+          if (member.getValue() instanceof Boolean) {
+            obj.setFlag((Boolean)member.getValue());
+          }
+          break;
+        case "help":
+          if (member.getValue() instanceof Boolean) {
+            obj.setHelp((Boolean)member.getValue());
+          }
+          break;
+        case "hidden":
+          if (member.getValue() instanceof Boolean) {
+            obj.setHidden((Boolean)member.getValue());
+          }
+          break;
+        case "longName":
+          if (member.getValue() instanceof String) {
+            obj.setLongName((String)member.getValue());
+          }
+          break;
+        case "multiValued":
+          if (member.getValue() instanceof Boolean) {
+            obj.setMultiValued((Boolean)member.getValue());
+          }
+          break;
+        case "name":
+          break;
+        case "required":
+          if (member.getValue() instanceof Boolean) {
+            obj.setRequired((Boolean)member.getValue());
+          }
+          break;
+        case "shortName":
+          if (member.getValue() instanceof String) {
+            obj.setShortName((String)member.getValue());
+          }
+          break;
+        case "singleValued":
+          if (member.getValue() instanceof Boolean) {
+            obj.setSingleValued((Boolean)member.getValue());
+          }
+          break;
+      }
+    }
+  }
+
+   static void toJson(Option obj, JsonObject json) {
+    toJson(obj, json.getMap());
+  }
+
+   static void toJson(Option obj, java.util.Map<String, Object> json) {
+    if (obj.getArgName() != null) {
+      json.put("argName", obj.getArgName());
+    }
+    if (obj.getChoices() != null) {
+      JsonArray array = new JsonArray();
+      obj.getChoices().forEach(item -> array.add(item));
+      json.put("choices", array);
+    }
+    if (obj.getDefaultValue() != null) {
+      json.put("defaultValue", obj.getDefaultValue());
+    }
+    if (obj.getDescription() != null) {
+      json.put("description", obj.getDescription());
+    }
+    json.put("flag", obj.isFlag());
+    json.put("help", obj.isHelp());
+    json.put("hidden", obj.isHidden());
+    if (obj.getLongName() != null) {
+      json.put("longName", obj.getLongName());
+    }
+    json.put("multiValued", obj.isMultiValued());
+    if (obj.getName() != null) {
+      json.put("name", obj.getName());
+    }
+    json.put("required", obj.isRequired());
+    if (obj.getShortName() != null) {
+      json.put("shortName", obj.getShortName());
+    }
+    json.put("singleValued", obj.isSingleValued());
+  }
+}
diff --git a/src/main/generated/io/vertx/core/datagram/DatagramSocketOptionsConverter.java b/src/main/generated/io/vertx/core/datagram/DatagramSocketOptionsConverter.java
new file mode 100644
--- /dev/null
+++ b/src/main/generated/io/vertx/core/datagram/DatagramSocketOptionsConverter.java
@@ -0,0 +1,59 @@
+package io.vertx.core.datagram;
+
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.json.JsonArray;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Converter for {@link io.vertx.core.datagram.DatagramSocketOptions}.
+ * NOTE: This class has been automatically generated from the {@link io.vertx.core.datagram.DatagramSocketOptions} original class using Vert.x codegen.
+ */
+ class DatagramSocketOptionsConverter {
+
+   static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, DatagramSocketOptions obj) {
+    for (java.util.Map.Entry<String, Object> member : json) {
+      switch (member.getKey()) {
+        case "broadcast":
+          if (member.getValue() instanceof Boolean) {
+            obj.setBroadcast((Boolean)member.getValue());
+          }
+          break;
+        case "ipV6":
+          if (member.getValue() instanceof Boolean) {
+            obj.setIpV6((Boolean)member.getValue());
+          }
+          break;
+        case "loopbackModeDisabled":
+          if (member.getValue() instanceof Boolean) {
+            obj.setLoopbackModeDisabled((Boolean)member.getValue());
+          }
+          break;
+        case "multicastNetworkInterface":
+          if (member.getValue() instanceof String) {
+            obj.setMulticastNetworkInterface((String)member.getValue());
+          }
+          break;
+        case "multicastTimeToLive":
+          if (member.getValue() instanceof Number) {
+            obj.setMulticastTimeToLive(((Number)member.getValue()).intValue());
+          }
+          break;
+      }
+    }
+  }
+
+   static void toJson(DatagramSocketOptions obj, JsonObject json) {
+    toJson(obj, json.getMap());
+  }
+
+   static void toJson(DatagramSocketOptions obj, java.util.Map<String, Object> json) {
+    json.put("broadcast", obj.isBroadcast());
+    json.put("ipV6", obj.isIpV6());
+    json.put("loopbackModeDisabled", obj.isLoopbackModeDisabled());
+    if (obj.getMulticastNetworkInterface() != null) {
+      json.put("multicastNetworkInterface", obj.getMulticastNetworkInterface());
+    }
+    json.put("multicastTimeToLive", obj.getMulticastTimeToLive());
+  }
+}
diff --git a/src/main/generated/io/vertx/core/dns/AddressResolverOptionsConverter.java b/src/main/generated/io/vertx/core/dns/AddressResolverOptionsConverter.java
new file mode 100644
--- /dev/null
+++ b/src/main/generated/io/vertx/core/dns/AddressResolverOptionsConverter.java
@@ -0,0 +1,127 @@
+package io.vertx.core.dns;
+
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.json.JsonArray;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Converter for {@link io.vertx.core.dns.AddressResolverOptions}.
+ * NOTE: This class has been automatically generated from the {@link io.vertx.core.dns.AddressResolverOptions} original class using Vert.x codegen.
+ */
+ class AddressResolverOptionsConverter {
+
+   static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, AddressResolverOptions obj) {
+    for (java.util.Map.Entry<String, Object> member : json) {
+      switch (member.getKey()) {
+        case "cacheMaxTimeToLive":
+          if (member.getValue() instanceof Number) {
+            obj.setCacheMaxTimeToLive(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "cacheMinTimeToLive":
+          if (member.getValue() instanceof Number) {
+            obj.setCacheMinTimeToLive(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "cacheNegativeTimeToLive":
+          if (member.getValue() instanceof Number) {
+            obj.setCacheNegativeTimeToLive(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "hostsPath":
+          if (member.getValue() instanceof String) {
+            obj.setHostsPath((String)member.getValue());
+          }
+          break;
+        case "hostsValue":
+          if (member.getValue() instanceof String) {
+            obj.setHostsValue(io.vertx.core.buffer.Buffer.buffer(java.util.Base64.getDecoder().decode((String)member.getValue())));
+          }
+          break;
+        case "maxQueries":
+          if (member.getValue() instanceof Number) {
+            obj.setMaxQueries(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "ndots":
+          if (member.getValue() instanceof Number) {
+            obj.setNdots(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "optResourceEnabled":
+          if (member.getValue() instanceof Boolean) {
+            obj.setOptResourceEnabled((Boolean)member.getValue());
+          }
+          break;
+        case "queryTimeout":
+          if (member.getValue() instanceof Number) {
+            obj.setQueryTimeout(((Number)member.getValue()).longValue());
+          }
+          break;
+        case "rdFlag":
+          if (member.getValue() instanceof Boolean) {
+            obj.setRdFlag((Boolean)member.getValue());
+          }
+          break;
+        case "rotateServers":
+          if (member.getValue() instanceof Boolean) {
+            obj.setRotateServers((Boolean)member.getValue());
+          }
+          break;
+        case "searchDomains":
+          if (member.getValue() instanceof JsonArray) {
+            java.util.ArrayList<java.lang.String> list =  new java.util.ArrayList<>();
+            ((Iterable<Object>)member.getValue()).forEach( item -> {
+              if (item instanceof String)
+                list.add((String)item);
+            });
+            obj.setSearchDomains(list);
+          }
+          break;
+        case "servers":
+          if (member.getValue() instanceof JsonArray) {
+            java.util.ArrayList<java.lang.String> list =  new java.util.ArrayList<>();
+            ((Iterable<Object>)member.getValue()).forEach( item -> {
+              if (item instanceof String)
+                list.add((String)item);
+            });
+            obj.setServers(list);
+          }
+          break;
+      }
+    }
+  }
+
+   static void toJson(AddressResolverOptions obj, JsonObject json) {
+    toJson(obj, json.getMap());
+  }
+
+   static void toJson(AddressResolverOptions obj, java.util.Map<String, Object> json) {
+    json.put("cacheMaxTimeToLive", obj.getCacheMaxTimeToLive());
+    json.put("cacheMinTimeToLive", obj.getCacheMinTimeToLive());
+    json.put("cacheNegativeTimeToLive", obj.getCacheNegativeTimeToLive());
+    if (obj.getHostsPath() != null) {
+      json.put("hostsPath", obj.getHostsPath());
+    }
+    if (obj.getHostsValue() != null) {
+      json.put("hostsValue", java.util.Base64.getEncoder().encodeToString(obj.getHostsValue().getBytes()));
+    }
+    json.put("maxQueries", obj.getMaxQueries());
+    json.put("ndots", obj.getNdots());
+    json.put("optResourceEnabled", obj.isOptResourceEnabled());
+    json.put("queryTimeout", obj.getQueryTimeout());
+    json.put("rdFlag", obj.getRdFlag());
+    json.put("rotateServers", obj.isRotateServers());
+    if (obj.getSearchDomains() != null) {
+      JsonArray array = new JsonArray();
+      obj.getSearchDomains().forEach(item -> array.add(item));
+      json.put("searchDomains", array);
+    }
+    if (obj.getServers() != null) {
+      JsonArray array = new JsonArray();
+      obj.getServers().forEach(item -> array.add(item));
+      json.put("servers", array);
+    }
+  }
+}
diff --git a/src/main/generated/io/vertx/core/dns/DnsClientOptionsConverter.java b/src/main/generated/io/vertx/core/dns/DnsClientOptionsConverter.java
new file mode 100644
--- /dev/null
+++ b/src/main/generated/io/vertx/core/dns/DnsClientOptionsConverter.java
@@ -0,0 +1,59 @@
+package io.vertx.core.dns;
+
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.json.JsonArray;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Converter for {@link io.vertx.core.dns.DnsClientOptions}.
+ * NOTE: This class has been automatically generated from the {@link io.vertx.core.dns.DnsClientOptions} original class using Vert.x codegen.
+ */
+public class DnsClientOptionsConverter {
+
+  public static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, DnsClientOptions obj) {
+    for (java.util.Map.Entry<String, Object> member : json) {
+      switch (member.getKey()) {
+        case "host":
+          if (member.getValue() instanceof String) {
+            obj.setHost((String)member.getValue());
+          }
+          break;
+        case "logActivity":
+          if (member.getValue() instanceof Boolean) {
+            obj.setLogActivity((Boolean)member.getValue());
+          }
+          break;
+        case "port":
+          if (member.getValue() instanceof Number) {
+            obj.setPort(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "queryTimeout":
+          if (member.getValue() instanceof Number) {
+            obj.setQueryTimeout(((Number)member.getValue()).longValue());
+          }
+          break;
+        case "recursionDesired":
+          if (member.getValue() instanceof Boolean) {
+            obj.setRecursionDesired((Boolean)member.getValue());
+          }
+          break;
+      }
+    }
+  }
+
+  public static void toJson(DnsClientOptions obj, JsonObject json) {
+    toJson(obj, json.getMap());
+  }
+
+  public static void toJson(DnsClientOptions obj, java.util.Map<String, Object> json) {
+    if (obj.getHost() != null) {
+      json.put("host", obj.getHost());
+    }
+    json.put("logActivity", obj.getLogActivity());
+    json.put("port", obj.getPort());
+    json.put("queryTimeout", obj.getQueryTimeout());
+    json.put("recursionDesired", obj.isRecursionDesired());
+  }
+}
diff --git a/src/main/generated/io/vertx/core/eventbus/EventBusOptionsConverter.java b/src/main/generated/io/vertx/core/eventbus/EventBusOptionsConverter.java
new file mode 100644
--- /dev/null
+++ b/src/main/generated/io/vertx/core/eventbus/EventBusOptionsConverter.java
@@ -0,0 +1,347 @@
+package io.vertx.core.eventbus;
+
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.json.JsonArray;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Converter for {@link io.vertx.core.eventbus.EventBusOptions}.
+ * NOTE: This class has been automatically generated from the {@link io.vertx.core.eventbus.EventBusOptions} original class using Vert.x codegen.
+ */
+ class EventBusOptionsConverter {
+
+   static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, EventBusOptions obj) {
+    for (java.util.Map.Entry<String, Object> member : json) {
+      switch (member.getKey()) {
+        case "acceptBacklog":
+          if (member.getValue() instanceof Number) {
+            obj.setAcceptBacklog(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "clientAuth":
+          if (member.getValue() instanceof String) {
+            obj.setClientAuth(io.vertx.core.http.ClientAuth.valueOf((String)member.getValue()));
+          }
+          break;
+        case "clusterPingInterval":
+          if (member.getValue() instanceof Number) {
+            obj.setClusterPingInterval(((Number)member.getValue()).longValue());
+          }
+          break;
+        case "clusterPingReplyInterval":
+          if (member.getValue() instanceof Number) {
+            obj.setClusterPingReplyInterval(((Number)member.getValue()).longValue());
+          }
+          break;
+        case "clusterPublicHost":
+          if (member.getValue() instanceof String) {
+            obj.setClusterPublicHost((String)member.getValue());
+          }
+          break;
+        case "clusterPublicPort":
+          if (member.getValue() instanceof Number) {
+            obj.setClusterPublicPort(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "clustered":
+          if (member.getValue() instanceof Boolean) {
+            obj.setClustered((Boolean)member.getValue());
+          }
+          break;
+        case "connectTimeout":
+          if (member.getValue() instanceof Number) {
+            obj.setConnectTimeout(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "crlPaths":
+          if (member.getValue() instanceof JsonArray) {
+            ((Iterable<Object>)member.getValue()).forEach( item -> {
+              if (item instanceof String)
+                obj.addCrlPath((String)item);
+            });
+          }
+          break;
+        case "crlValues":
+          if (member.getValue() instanceof JsonArray) {
+            ((Iterable<Object>)member.getValue()).forEach( item -> {
+              if (item instanceof String)
+                obj.addCrlValue(io.vertx.core.buffer.Buffer.buffer(java.util.Base64.getDecoder().decode((String)item)));
+            });
+          }
+          break;
+        case "enabledCipherSuites":
+          if (member.getValue() instanceof JsonArray) {
+            ((Iterable<Object>)member.getValue()).forEach( item -> {
+              if (item instanceof String)
+                obj.addEnabledCipherSuite((String)item);
+            });
+          }
+          break;
+        case "enabledSecureTransportProtocols":
+          if (member.getValue() instanceof JsonArray) {
+            java.util.LinkedHashSet<java.lang.String> list =  new java.util.LinkedHashSet<>();
+            ((Iterable<Object>)member.getValue()).forEach( item -> {
+              if (item instanceof String)
+                list.add((String)item);
+            });
+            obj.setEnabledSecureTransportProtocols(list);
+          }
+          break;
+        case "host":
+          if (member.getValue() instanceof String) {
+            obj.setHost((String)member.getValue());
+          }
+          break;
+        case "idleTimeout":
+          if (member.getValue() instanceof Number) {
+            obj.setIdleTimeout(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "idleTimeoutUnit":
+          if (member.getValue() instanceof String) {
+            obj.setIdleTimeoutUnit(java.util.concurrent.TimeUnit.valueOf((String)member.getValue()));
+          }
+          break;
+        case "jdkSslEngineOptions":
+          if (member.getValue() instanceof JsonObject) {
+            obj.setJdkSslEngineOptions(new io.vertx.core.net.JdkSSLEngineOptions((JsonObject)member.getValue()));
+          }
+          break;
+        case "keyStoreOptions":
+          if (member.getValue() instanceof JsonObject) {
+            obj.setKeyStoreOptions(new io.vertx.core.net.JksOptions((JsonObject)member.getValue()));
+          }
+          break;
+        case "logActivity":
+          if (member.getValue() instanceof Boolean) {
+            obj.setLogActivity((Boolean)member.getValue());
+          }
+          break;
+        case "openSslEngineOptions":
+          if (member.getValue() instanceof JsonObject) {
+            obj.setOpenSslEngineOptions(new io.vertx.core.net.OpenSSLEngineOptions((JsonObject)member.getValue()));
+          }
+          break;
+        case "pemKeyCertOptions":
+          if (member.getValue() instanceof JsonObject) {
+            obj.setPemKeyCertOptions(new io.vertx.core.net.PemKeyCertOptions((JsonObject)member.getValue()));
+          }
+          break;
+        case "pemTrustOptions":
+          if (member.getValue() instanceof JsonObject) {
+            obj.setPemTrustOptions(new io.vertx.core.net.PemTrustOptions((JsonObject)member.getValue()));
+          }
+          break;
+        case "pfxKeyCertOptions":
+          if (member.getValue() instanceof JsonObject) {
+            obj.setPfxKeyCertOptions(new io.vertx.core.net.PfxOptions((JsonObject)member.getValue()));
+          }
+          break;
+        case "pfxTrustOptions":
+          if (member.getValue() instanceof JsonObject) {
+            obj.setPfxTrustOptions(new io.vertx.core.net.PfxOptions((JsonObject)member.getValue()));
+          }
+          break;
+        case "port":
+          if (member.getValue() instanceof Number) {
+            obj.setPort(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "receiveBufferSize":
+          if (member.getValue() instanceof Number) {
+            obj.setReceiveBufferSize(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "reconnectAttempts":
+          if (member.getValue() instanceof Number) {
+            obj.setReconnectAttempts(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "reconnectInterval":
+          if (member.getValue() instanceof Number) {
+            obj.setReconnectInterval(((Number)member.getValue()).longValue());
+          }
+          break;
+        case "reuseAddress":
+          if (member.getValue() instanceof Boolean) {
+            obj.setReuseAddress((Boolean)member.getValue());
+          }
+          break;
+        case "reusePort":
+          if (member.getValue() instanceof Boolean) {
+            obj.setReusePort((Boolean)member.getValue());
+          }
+          break;
+        case "sendBufferSize":
+          if (member.getValue() instanceof Number) {
+            obj.setSendBufferSize(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "soLinger":
+          if (member.getValue() instanceof Number) {
+            obj.setSoLinger(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "ssl":
+          if (member.getValue() instanceof Boolean) {
+            obj.setSsl((Boolean)member.getValue());
+          }
+          break;
+        case "sslHandshakeTimeout":
+          if (member.getValue() instanceof Number) {
+            obj.setSslHandshakeTimeout(((Number)member.getValue()).longValue());
+          }
+          break;
+        case "sslHandshakeTimeoutUnit":
+          if (member.getValue() instanceof String) {
+            obj.setSslHandshakeTimeoutUnit(java.util.concurrent.TimeUnit.valueOf((String)member.getValue()));
+          }
+          break;
+        case "tcpCork":
+          if (member.getValue() instanceof Boolean) {
+            obj.setTcpCork((Boolean)member.getValue());
+          }
+          break;
+        case "tcpFastOpen":
+          if (member.getValue() instanceof Boolean) {
+            obj.setTcpFastOpen((Boolean)member.getValue());
+          }
+          break;
+        case "tcpKeepAlive":
+          if (member.getValue() instanceof Boolean) {
+            obj.setTcpKeepAlive((Boolean)member.getValue());
+          }
+          break;
+        case "tcpNoDelay":
+          if (member.getValue() instanceof Boolean) {
+            obj.setTcpNoDelay((Boolean)member.getValue());
+          }
+          break;
+        case "tcpQuickAck":
+          if (member.getValue() instanceof Boolean) {
+            obj.setTcpQuickAck((Boolean)member.getValue());
+          }
+          break;
+        case "trafficClass":
+          if (member.getValue() instanceof Number) {
+            obj.setTrafficClass(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "trustAll":
+          if (member.getValue() instanceof Boolean) {
+            obj.setTrustAll((Boolean)member.getValue());
+          }
+          break;
+        case "trustStoreOptions":
+          if (member.getValue() instanceof JsonObject) {
+            obj.setTrustStoreOptions(new io.vertx.core.net.JksOptions((JsonObject)member.getValue()));
+          }
+          break;
+        case "useAlpn":
+          if (member.getValue() instanceof Boolean) {
+            obj.setUseAlpn((Boolean)member.getValue());
+          }
+          break;
+        case "usePooledBuffers":
+          if (member.getValue() instanceof Boolean) {
+            obj.setUsePooledBuffers((Boolean)member.getValue());
+          }
+          break;
+      }
+    }
+  }
+
+   static void toJson(EventBusOptions obj, JsonObject json) {
+    toJson(obj, json.getMap());
+  }
+
+   static void toJson(EventBusOptions obj, java.util.Map<String, Object> json) {
+    json.put("acceptBacklog", obj.getAcceptBacklog());
+    if (obj.getClientAuth() != null) {
+      json.put("clientAuth", obj.getClientAuth().name());
+    }
+    json.put("clusterPingInterval", obj.getClusterPingInterval());
+    json.put("clusterPingReplyInterval", obj.getClusterPingReplyInterval());
+    if (obj.getClusterPublicHost() != null) {
+      json.put("clusterPublicHost", obj.getClusterPublicHost());
+    }
+    json.put("clusterPublicPort", obj.getClusterPublicPort());
+    json.put("clustered", obj.isClustered());
+    json.put("connectTimeout", obj.getConnectTimeout());
+    if (obj.getCrlPaths() != null) {
+      JsonArray array = new JsonArray();
+      obj.getCrlPaths().forEach(item -> array.add(item));
+      json.put("crlPaths", array);
+    }
+    if (obj.getCrlValues() != null) {
+      JsonArray array = new JsonArray();
+      obj.getCrlValues().forEach(item -> array.add(java.util.Base64.getEncoder().encodeToString(item.getBytes())));
+      json.put("crlValues", array);
+    }
+    if (obj.getEnabledCipherSuites() != null) {
+      JsonArray array = new JsonArray();
+      obj.getEnabledCipherSuites().forEach(item -> array.add(item));
+      json.put("enabledCipherSuites", array);
+    }
+    if (obj.getEnabledSecureTransportProtocols() != null) {
+      JsonArray array = new JsonArray();
+      obj.getEnabledSecureTransportProtocols().forEach(item -> array.add(item));
+      json.put("enabledSecureTransportProtocols", array);
+    }
+    if (obj.getHost() != null) {
+      json.put("host", obj.getHost());
+    }
+    json.put("idleTimeout", obj.getIdleTimeout());
+    if (obj.getIdleTimeoutUnit() != null) {
+      json.put("idleTimeoutUnit", obj.getIdleTimeoutUnit().name());
+    }
+    if (obj.getJdkSslEngineOptions() != null) {
+      json.put("jdkSslEngineOptions", obj.getJdkSslEngineOptions().toJson());
+    }
+    if (obj.getKeyStoreOptions() != null) {
+      json.put("keyStoreOptions", obj.getKeyStoreOptions().toJson());
+    }
+    json.put("logActivity", obj.getLogActivity());
+    if (obj.getOpenSslEngineOptions() != null) {
+      json.put("openSslEngineOptions", obj.getOpenSslEngineOptions().toJson());
+    }
+    if (obj.getPemKeyCertOptions() != null) {
+      json.put("pemKeyCertOptions", obj.getPemKeyCertOptions().toJson());
+    }
+    if (obj.getPemTrustOptions() != null) {
+      json.put("pemTrustOptions", obj.getPemTrustOptions().toJson());
+    }
+    if (obj.getPfxKeyCertOptions() != null) {
+      json.put("pfxKeyCertOptions", obj.getPfxKeyCertOptions().toJson());
+    }
+    if (obj.getPfxTrustOptions() != null) {
+      json.put("pfxTrustOptions", obj.getPfxTrustOptions().toJson());
+    }
+    json.put("port", obj.getPort());
+    json.put("receiveBufferSize", obj.getReceiveBufferSize());
+    json.put("reconnectAttempts", obj.getReconnectAttempts());
+    json.put("reconnectInterval", obj.getReconnectInterval());
+    json.put("reuseAddress", obj.isReuseAddress());
+    json.put("reusePort", obj.isReusePort());
+    json.put("sendBufferSize", obj.getSendBufferSize());
+    json.put("soLinger", obj.getSoLinger());
+    json.put("ssl", obj.isSsl());
+    json.put("sslHandshakeTimeout", obj.getSslHandshakeTimeout());
+    if (obj.getSslHandshakeTimeoutUnit() != null) {
+      json.put("sslHandshakeTimeoutUnit", obj.getSslHandshakeTimeoutUnit().name());
+    }
+    json.put("tcpCork", obj.isTcpCork());
+    json.put("tcpFastOpen", obj.isTcpFastOpen());
+    json.put("tcpKeepAlive", obj.isTcpKeepAlive());
+    json.put("tcpNoDelay", obj.isTcpNoDelay());
+    json.put("tcpQuickAck", obj.isTcpQuickAck());
+    json.put("trafficClass", obj.getTrafficClass());
+    json.put("trustAll", obj.isTrustAll());
+    if (obj.getTrustStoreOptions() != null) {
+      json.put("trustStoreOptions", obj.getTrustStoreOptions().toJson());
+    }
+    json.put("useAlpn", obj.isUseAlpn());
+    json.put("usePooledBuffers", obj.isUsePooledBuffers());
+  }
+}
diff --git a/src/main/generated/io/vertx/core/file/CopyOptionsConverter.java b/src/main/generated/io/vertx/core/file/CopyOptionsConverter.java
new file mode 100644
--- /dev/null
+++ b/src/main/generated/io/vertx/core/file/CopyOptionsConverter.java
@@ -0,0 +1,51 @@
+package io.vertx.core.file;
+
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.json.JsonArray;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Converter for {@link io.vertx.core.file.CopyOptions}.
+ * NOTE: This class has been automatically generated from the {@link io.vertx.core.file.CopyOptions} original class using Vert.x codegen.
+ */
+ class CopyOptionsConverter {
+
+   static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, CopyOptions obj) {
+    for (java.util.Map.Entry<String, Object> member : json) {
+      switch (member.getKey()) {
+        case "atomicMove":
+          if (member.getValue() instanceof Boolean) {
+            obj.setAtomicMove((Boolean)member.getValue());
+          }
+          break;
+        case "copyAttributes":
+          if (member.getValue() instanceof Boolean) {
+            obj.setCopyAttributes((Boolean)member.getValue());
+          }
+          break;
+        case "nofollowLinks":
+          if (member.getValue() instanceof Boolean) {
+            obj.setNofollowLinks((Boolean)member.getValue());
+          }
+          break;
+        case "replaceExisting":
+          if (member.getValue() instanceof Boolean) {
+            obj.setReplaceExisting((Boolean)member.getValue());
+          }
+          break;
+      }
+    }
+  }
+
+   static void toJson(CopyOptions obj, JsonObject json) {
+    toJson(obj, json.getMap());
+  }
+
+   static void toJson(CopyOptions obj, java.util.Map<String, Object> json) {
+    json.put("atomicMove", obj.isAtomicMove());
+    json.put("copyAttributes", obj.isCopyAttributes());
+    json.put("nofollowLinks", obj.isNofollowLinks());
+    json.put("replaceExisting", obj.isReplaceExisting());
+  }
+}
diff --git a/src/main/generated/io/vertx/core/file/FileSystemOptionsConverter.java b/src/main/generated/io/vertx/core/file/FileSystemOptionsConverter.java
new file mode 100644
--- /dev/null
+++ b/src/main/generated/io/vertx/core/file/FileSystemOptionsConverter.java
@@ -0,0 +1,47 @@
+package io.vertx.core.file;
+
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.json.JsonArray;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Converter for {@link io.vertx.core.file.FileSystemOptions}.
+ * NOTE: This class has been automatically generated from the {@link io.vertx.core.file.FileSystemOptions} original class using Vert.x codegen.
+ */
+ class FileSystemOptionsConverter {
+
+   static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, FileSystemOptions obj) {
+    for (java.util.Map.Entry<String, Object> member : json) {
+      switch (member.getKey()) {
+        case "classPathResolvingEnabled":
+          if (member.getValue() instanceof Boolean) {
+            obj.setClassPathResolvingEnabled((Boolean)member.getValue());
+          }
+          break;
+        case "fileCacheDir":
+          if (member.getValue() instanceof String) {
+            obj.setFileCacheDir((String)member.getValue());
+          }
+          break;
+        case "fileCachingEnabled":
+          if (member.getValue() instanceof Boolean) {
+            obj.setFileCachingEnabled((Boolean)member.getValue());
+          }
+          break;
+      }
+    }
+  }
+
+   static void toJson(FileSystemOptions obj, JsonObject json) {
+    toJson(obj, json.getMap());
+  }
+
+   static void toJson(FileSystemOptions obj, java.util.Map<String, Object> json) {
+    json.put("classPathResolvingEnabled", obj.isClassPathResolvingEnabled());
+    if (obj.getFileCacheDir() != null) {
+      json.put("fileCacheDir", obj.getFileCacheDir());
+    }
+    json.put("fileCachingEnabled", obj.isFileCachingEnabled());
+  }
+}
diff --git a/src/main/generated/io/vertx/core/file/OpenOptionsConverter.java b/src/main/generated/io/vertx/core/file/OpenOptionsConverter.java
new file mode 100644
--- /dev/null
+++ b/src/main/generated/io/vertx/core/file/OpenOptionsConverter.java
@@ -0,0 +1,95 @@
+package io.vertx.core.file;
+
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.json.JsonArray;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Converter for {@link io.vertx.core.file.OpenOptions}.
+ * NOTE: This class has been automatically generated from the {@link io.vertx.core.file.OpenOptions} original class using Vert.x codegen.
+ */
+ class OpenOptionsConverter {
+
+   static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, OpenOptions obj) {
+    for (java.util.Map.Entry<String, Object> member : json) {
+      switch (member.getKey()) {
+        case "append":
+          if (member.getValue() instanceof Boolean) {
+            obj.setAppend((Boolean)member.getValue());
+          }
+          break;
+        case "create":
+          if (member.getValue() instanceof Boolean) {
+            obj.setCreate((Boolean)member.getValue());
+          }
+          break;
+        case "createNew":
+          if (member.getValue() instanceof Boolean) {
+            obj.setCreateNew((Boolean)member.getValue());
+          }
+          break;
+        case "deleteOnClose":
+          if (member.getValue() instanceof Boolean) {
+            obj.setDeleteOnClose((Boolean)member.getValue());
+          }
+          break;
+        case "dsync":
+          if (member.getValue() instanceof Boolean) {
+            obj.setDsync((Boolean)member.getValue());
+          }
+          break;
+        case "perms":
+          if (member.getValue() instanceof String) {
+            obj.setPerms((String)member.getValue());
+          }
+          break;
+        case "read":
+          if (member.getValue() instanceof Boolean) {
+            obj.setRead((Boolean)member.getValue());
+          }
+          break;
+        case "sparse":
+          if (member.getValue() instanceof Boolean) {
+            obj.setSparse((Boolean)member.getValue());
+          }
+          break;
+        case "sync":
+          if (member.getValue() instanceof Boolean) {
+            obj.setSync((Boolean)member.getValue());
+          }
+          break;
+        case "truncateExisting":
+          if (member.getValue() instanceof Boolean) {
+            obj.setTruncateExisting((Boolean)member.getValue());
+          }
+          break;
+        case "write":
+          if (member.getValue() instanceof Boolean) {
+            obj.setWrite((Boolean)member.getValue());
+          }
+          break;
+      }
+    }
+  }
+
+   static void toJson(OpenOptions obj, JsonObject json) {
+    toJson(obj, json.getMap());
+  }
+
+   static void toJson(OpenOptions obj, java.util.Map<String, Object> json) {
+    json.put("append", obj.isAppend());
+    json.put("create", obj.isCreate());
+    json.put("createNew", obj.isCreateNew());
+    json.put("deleteOnClose", obj.isDeleteOnClose());
+    json.put("dsync", obj.isDsync());
+    if (obj.getPerms() != null) {
+      json.put("perms", obj.getPerms());
+    }
+    json.put("read", obj.isRead());
+    json.put("sparse", obj.isSparse());
+    json.put("sync", obj.isSync());
+    json.put("truncateExisting", obj.isTruncateExisting());
+    json.put("write", obj.isWrite());
+  }
+}
diff --git a/src/main/generated/io/vertx/core/http/GoAwayConverter.java b/src/main/generated/io/vertx/core/http/GoAwayConverter.java
new file mode 100644
--- /dev/null
+++ b/src/main/generated/io/vertx/core/http/GoAwayConverter.java
@@ -0,0 +1,47 @@
+package io.vertx.core.http;
+
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.json.JsonArray;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Converter for {@link io.vertx.core.http.GoAway}.
+ * NOTE: This class has been automatically generated from the {@link io.vertx.core.http.GoAway} original class using Vert.x codegen.
+ */
+ class GoAwayConverter {
+
+   static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, GoAway obj) {
+    for (java.util.Map.Entry<String, Object> member : json) {
+      switch (member.getKey()) {
+        case "debugData":
+          if (member.getValue() instanceof String) {
+            obj.setDebugData(io.vertx.core.buffer.Buffer.buffer(java.util.Base64.getDecoder().decode((String)member.getValue())));
+          }
+          break;
+        case "errorCode":
+          if (member.getValue() instanceof Number) {
+            obj.setErrorCode(((Number)member.getValue()).longValue());
+          }
+          break;
+        case "lastStreamId":
+          if (member.getValue() instanceof Number) {
+            obj.setLastStreamId(((Number)member.getValue()).intValue());
+          }
+          break;
+      }
+    }
+  }
+
+   static void toJson(GoAway obj, JsonObject json) {
+    toJson(obj, json.getMap());
+  }
+
+   static void toJson(GoAway obj, java.util.Map<String, Object> json) {
+    if (obj.getDebugData() != null) {
+      json.put("debugData", java.util.Base64.getEncoder().encodeToString(obj.getDebugData().getBytes()));
+    }
+    json.put("errorCode", obj.getErrorCode());
+    json.put("lastStreamId", obj.getLastStreamId());
+  }
+}
diff --git a/src/main/generated/io/vertx/core/http/Http2SettingsConverter.java b/src/main/generated/io/vertx/core/http/Http2SettingsConverter.java
new file mode 100644
--- /dev/null
+++ b/src/main/generated/io/vertx/core/http/Http2SettingsConverter.java
@@ -0,0 +1,63 @@
+package io.vertx.core.http;
+
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.json.JsonArray;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Converter for {@link io.vertx.core.http.Http2Settings}.
+ * NOTE: This class has been automatically generated from the {@link io.vertx.core.http.Http2Settings} original class using Vert.x codegen.
+ */
+ class Http2SettingsConverter {
+
+   static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, Http2Settings obj) {
+    for (java.util.Map.Entry<String, Object> member : json) {
+      switch (member.getKey()) {
+        case "headerTableSize":
+          if (member.getValue() instanceof Number) {
+            obj.setHeaderTableSize(((Number)member.getValue()).longValue());
+          }
+          break;
+        case "initialWindowSize":
+          if (member.getValue() instanceof Number) {
+            obj.setInitialWindowSize(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "maxConcurrentStreams":
+          if (member.getValue() instanceof Number) {
+            obj.setMaxConcurrentStreams(((Number)member.getValue()).longValue());
+          }
+          break;
+        case "maxFrameSize":
+          if (member.getValue() instanceof Number) {
+            obj.setMaxFrameSize(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "maxHeaderListSize":
+          if (member.getValue() instanceof Number) {
+            obj.setMaxHeaderListSize(((Number)member.getValue()).longValue());
+          }
+          break;
+        case "pushEnabled":
+          if (member.getValue() instanceof Boolean) {
+            obj.setPushEnabled((Boolean)member.getValue());
+          }
+          break;
+      }
+    }
+  }
+
+   static void toJson(Http2Settings obj, JsonObject json) {
+    toJson(obj, json.getMap());
+  }
+
+   static void toJson(Http2Settings obj, java.util.Map<String, Object> json) {
+    json.put("headerTableSize", obj.getHeaderTableSize());
+    json.put("initialWindowSize", obj.getInitialWindowSize());
+    json.put("maxConcurrentStreams", obj.getMaxConcurrentStreams());
+    json.put("maxFrameSize", obj.getMaxFrameSize());
+    json.put("maxHeaderListSize", obj.getMaxHeaderListSize());
+    json.put("pushEnabled", obj.isPushEnabled());
+  }
+}
diff --git a/src/main/generated/io/vertx/core/http/HttpClientOptionsConverter.java b/src/main/generated/io/vertx/core/http/HttpClientOptionsConverter.java
new file mode 100644
--- /dev/null
+++ b/src/main/generated/io/vertx/core/http/HttpClientOptionsConverter.java
@@ -0,0 +1,292 @@
+package io.vertx.core.http;
+
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.json.JsonArray;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Converter for {@link io.vertx.core.http.HttpClientOptions}.
+ * NOTE: This class has been automatically generated from the {@link io.vertx.core.http.HttpClientOptions} original class using Vert.x codegen.
+ */
+ class HttpClientOptionsConverter {
+
+   static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, HttpClientOptions obj) {
+    for (java.util.Map.Entry<String, Object> member : json) {
+      switch (member.getKey()) {
+        case "alpnVersions":
+          if (member.getValue() instanceof JsonArray) {
+            java.util.ArrayList<io.vertx.core.http.HttpVersion> list =  new java.util.ArrayList<>();
+            ((Iterable<Object>)member.getValue()).forEach( item -> {
+              if (item instanceof String)
+                list.add(io.vertx.core.http.HttpVersion.valueOf((String)item));
+            });
+            obj.setAlpnVersions(list);
+          }
+          break;
+        case "decoderInitialBufferSize":
+          if (member.getValue() instanceof Number) {
+            obj.setDecoderInitialBufferSize(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "defaultHost":
+          if (member.getValue() instanceof String) {
+            obj.setDefaultHost((String)member.getValue());
+          }
+          break;
+        case "defaultPort":
+          if (member.getValue() instanceof Number) {
+            obj.setDefaultPort(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "forceSni":
+          if (member.getValue() instanceof Boolean) {
+            obj.setForceSni((Boolean)member.getValue());
+          }
+          break;
+        case "http2ClearTextUpgrade":
+          if (member.getValue() instanceof Boolean) {
+            obj.setHttp2ClearTextUpgrade((Boolean)member.getValue());
+          }
+          break;
+        case "http2ConnectionWindowSize":
+          if (member.getValue() instanceof Number) {
+            obj.setHttp2ConnectionWindowSize(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "http2KeepAliveTimeout":
+          if (member.getValue() instanceof Number) {
+            obj.setHttp2KeepAliveTimeout(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "http2MaxPoolSize":
+          if (member.getValue() instanceof Number) {
+            obj.setHttp2MaxPoolSize(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "http2MultiplexingLimit":
+          if (member.getValue() instanceof Number) {
+            obj.setHttp2MultiplexingLimit(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "initialSettings":
+          if (member.getValue() instanceof JsonObject) {
+            obj.setInitialSettings(new io.vertx.core.http.Http2Settings((JsonObject)member.getValue()));
+          }
+          break;
+        case "keepAlive":
+          if (member.getValue() instanceof Boolean) {
+            obj.setKeepAlive((Boolean)member.getValue());
+          }
+          break;
+        case "keepAliveTimeout":
+          if (member.getValue() instanceof Number) {
+            obj.setKeepAliveTimeout(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "maxChunkSize":
+          if (member.getValue() instanceof Number) {
+            obj.setMaxChunkSize(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "maxHeaderSize":
+          if (member.getValue() instanceof Number) {
+            obj.setMaxHeaderSize(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "maxInitialLineLength":
+          if (member.getValue() instanceof Number) {
+            obj.setMaxInitialLineLength(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "maxPoolSize":
+          if (member.getValue() instanceof Number) {
+            obj.setMaxPoolSize(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "maxRedirects":
+          if (member.getValue() instanceof Number) {
+            obj.setMaxRedirects(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "maxWaitQueueSize":
+          if (member.getValue() instanceof Number) {
+            obj.setMaxWaitQueueSize(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "maxWebSocketFrameSize":
+          if (member.getValue() instanceof Number) {
+            obj.setMaxWebSocketFrameSize(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "maxWebSocketMessageSize":
+          if (member.getValue() instanceof Number) {
+            obj.setMaxWebSocketMessageSize(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "maxWebsocketFrameSize":
+          if (member.getValue() instanceof Number) {
+            obj.setMaxWebsocketFrameSize(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "maxWebsocketMessageSize":
+          if (member.getValue() instanceof Number) {
+            obj.setMaxWebsocketMessageSize(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "pipelining":
+          if (member.getValue() instanceof Boolean) {
+            obj.setPipelining((Boolean)member.getValue());
+          }
+          break;
+        case "pipeliningLimit":
+          if (member.getValue() instanceof Number) {
+            obj.setPipeliningLimit(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "poolCleanerPeriod":
+          if (member.getValue() instanceof Number) {
+            obj.setPoolCleanerPeriod(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "protocolVersion":
+          if (member.getValue() instanceof String) {
+            obj.setProtocolVersion(io.vertx.core.http.HttpVersion.valueOf((String)member.getValue()));
+          }
+          break;
+        case "sendUnmaskedFrames":
+          if (member.getValue() instanceof Boolean) {
+            obj.setSendUnmaskedFrames((Boolean)member.getValue());
+          }
+          break;
+        case "tryUseCompression":
+          if (member.getValue() instanceof Boolean) {
+            obj.setTryUseCompression((Boolean)member.getValue());
+          }
+          break;
+        case "tryUsePerFrameWebSocketCompression":
+          if (member.getValue() instanceof Boolean) {
+            obj.setTryUsePerFrameWebSocketCompression((Boolean)member.getValue());
+          }
+          break;
+        case "tryUsePerFrameWebsocketCompression":
+          if (member.getValue() instanceof Boolean) {
+            obj.setTryUsePerFrameWebsocketCompression((Boolean)member.getValue());
+          }
+          break;
+        case "tryUsePerMessageWebSocketCompression":
+          if (member.getValue() instanceof Boolean) {
+            obj.setTryUsePerMessageWebSocketCompression((Boolean)member.getValue());
+          }
+          break;
+        case "tryUsePerMessageWebsocketCompression":
+          if (member.getValue() instanceof Boolean) {
+            obj.setTryUsePerMessageWebsocketCompression((Boolean)member.getValue());
+          }
+          break;
+        case "tryWebSocketDeflateFrameCompression":
+          break;
+        case "tryWebsocketDeflateFrameCompression":
+          break;
+        case "verifyHost":
+          if (member.getValue() instanceof Boolean) {
+            obj.setVerifyHost((Boolean)member.getValue());
+          }
+          break;
+        case "webSocketClosingTimeout":
+          if (member.getValue() instanceof Number) {
+            obj.setWebSocketClosingTimeout(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "webSocketCompressionAllowClientNoContext":
+          if (member.getValue() instanceof Boolean) {
+            obj.setWebSocketCompressionAllowClientNoContext((Boolean)member.getValue());
+          }
+          break;
+        case "webSocketCompressionLevel":
+          if (member.getValue() instanceof Number) {
+            obj.setWebSocketCompressionLevel(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "webSocketCompressionRequestServerNoContext":
+          if (member.getValue() instanceof Boolean) {
+            obj.setWebSocketCompressionRequestServerNoContext((Boolean)member.getValue());
+          }
+          break;
+        case "websocketCompressionAllowClientNoContext":
+          if (member.getValue() instanceof Boolean) {
+            obj.setWebsocketCompressionAllowClientNoContext((Boolean)member.getValue());
+          }
+          break;
+        case "websocketCompressionLevel":
+          if (member.getValue() instanceof Number) {
+            obj.setWebsocketCompressionLevel(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "websocketCompressionRequestServerNoContext":
+          if (member.getValue() instanceof Boolean) {
+            obj.setWebsocketCompressionRequestServerNoContext((Boolean)member.getValue());
+          }
+          break;
+      }
+    }
+  }
+
+   static void toJson(HttpClientOptions obj, JsonObject json) {
+    toJson(obj, json.getMap());
+  }
+
+   static void toJson(HttpClientOptions obj, java.util.Map<String, Object> json) {
+    if (obj.getAlpnVersions() != null) {
+      JsonArray array = new JsonArray();
+      obj.getAlpnVersions().forEach(item -> array.add(item.name()));
+      json.put("alpnVersions", array);
+    }
+    json.put("decoderInitialBufferSize", obj.getDecoderInitialBufferSize());
+    if (obj.getDefaultHost() != null) {
+      json.put("defaultHost", obj.getDefaultHost());
+    }
+    json.put("defaultPort", obj.getDefaultPort());
+    json.put("forceSni", obj.isForceSni());
+    json.put("http2ClearTextUpgrade", obj.isHttp2ClearTextUpgrade());
+    json.put("http2ConnectionWindowSize", obj.getHttp2ConnectionWindowSize());
+    json.put("http2KeepAliveTimeout", obj.getHttp2KeepAliveTimeout());
+    json.put("http2MaxPoolSize", obj.getHttp2MaxPoolSize());
+    json.put("http2MultiplexingLimit", obj.getHttp2MultiplexingLimit());
+    if (obj.getInitialSettings() != null) {
+      json.put("initialSettings", obj.getInitialSettings().toJson());
+    }
+    json.put("keepAlive", obj.isKeepAlive());
+    json.put("keepAliveTimeout", obj.getKeepAliveTimeout());
+    json.put("maxChunkSize", obj.getMaxChunkSize());
+    json.put("maxHeaderSize", obj.getMaxHeaderSize());
+    json.put("maxInitialLineLength", obj.getMaxInitialLineLength());
+    json.put("maxPoolSize", obj.getMaxPoolSize());
+    json.put("maxRedirects", obj.getMaxRedirects());
+    json.put("maxWaitQueueSize", obj.getMaxWaitQueueSize());
+    json.put("maxWebSocketFrameSize", obj.getMaxWebSocketFrameSize());
+    json.put("maxWebSocketMessageSize", obj.getMaxWebSocketMessageSize());
+    json.put("maxWebsocketFrameSize", obj.getMaxWebsocketFrameSize());
+    json.put("maxWebsocketMessageSize", obj.getMaxWebsocketMessageSize());
+    json.put("pipelining", obj.isPipelining());
+    json.put("pipeliningLimit", obj.getPipeliningLimit());
+    json.put("poolCleanerPeriod", obj.getPoolCleanerPeriod());
+    if (obj.getProtocolVersion() != null) {
+      json.put("protocolVersion", obj.getProtocolVersion().name());
+    }
+    json.put("sendUnmaskedFrames", obj.isSendUnmaskedFrames());
+    json.put("tryUseCompression", obj.isTryUseCompression());
+    json.put("tryUsePerMessageWebSocketCompression", obj.getTryUsePerMessageWebSocketCompression());
+    json.put("tryUsePerMessageWebsocketCompression", obj.getTryUsePerMessageWebsocketCompression());
+    json.put("tryWebSocketDeflateFrameCompression", obj.getTryWebSocketDeflateFrameCompression());
+    json.put("tryWebsocketDeflateFrameCompression", obj.getTryWebsocketDeflateFrameCompression());
+    json.put("verifyHost", obj.isVerifyHost());
+    json.put("webSocketClosingTimeout", obj.getWebSocketClosingTimeout());
+    json.put("webSocketCompressionAllowClientNoContext", obj.getWebSocketCompressionAllowClientNoContext());
+    json.put("webSocketCompressionLevel", obj.getWebSocketCompressionLevel());
+    json.put("webSocketCompressionRequestServerNoContext", obj.getWebSocketCompressionRequestServerNoContext());
+    json.put("websocketCompressionAllowClientNoContext", obj.getWebsocketCompressionAllowClientNoContext());
+    json.put("websocketCompressionLevel", obj.getWebsocketCompressionLevel());
+    json.put("websocketCompressionRequestServerNoContext", obj.getWebsocketCompressionRequestServerNoContext());
+  }
+}
diff --git a/src/main/generated/io/vertx/core/http/HttpServerOptionsConverter.java b/src/main/generated/io/vertx/core/http/HttpServerOptionsConverter.java
new file mode 100644
--- /dev/null
+++ b/src/main/generated/io/vertx/core/http/HttpServerOptionsConverter.java
@@ -0,0 +1,223 @@
+package io.vertx.core.http;
+
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.json.JsonArray;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Converter for {@link io.vertx.core.http.HttpServerOptions}.
+ * NOTE: This class has been automatically generated from the {@link io.vertx.core.http.HttpServerOptions} original class using Vert.x codegen.
+ */
+ class HttpServerOptionsConverter {
+
+   static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, HttpServerOptions obj) {
+    for (java.util.Map.Entry<String, Object> member : json) {
+      switch (member.getKey()) {
+        case "acceptUnmaskedFrames":
+          if (member.getValue() instanceof Boolean) {
+            obj.setAcceptUnmaskedFrames((Boolean)member.getValue());
+          }
+          break;
+        case "alpnVersions":
+          if (member.getValue() instanceof JsonArray) {
+            java.util.ArrayList<io.vertx.core.http.HttpVersion> list =  new java.util.ArrayList<>();
+            ((Iterable<Object>)member.getValue()).forEach( item -> {
+              if (item instanceof String)
+                list.add(io.vertx.core.http.HttpVersion.valueOf((String)item));
+            });
+            obj.setAlpnVersions(list);
+          }
+          break;
+        case "compressionLevel":
+          if (member.getValue() instanceof Number) {
+            obj.setCompressionLevel(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "compressionSupported":
+          if (member.getValue() instanceof Boolean) {
+            obj.setCompressionSupported((Boolean)member.getValue());
+          }
+          break;
+        case "decoderInitialBufferSize":
+          if (member.getValue() instanceof Number) {
+            obj.setDecoderInitialBufferSize(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "decompressionSupported":
+          if (member.getValue() instanceof Boolean) {
+            obj.setDecompressionSupported((Boolean)member.getValue());
+          }
+          break;
+        case "handle100ContinueAutomatically":
+          if (member.getValue() instanceof Boolean) {
+            obj.setHandle100ContinueAutomatically((Boolean)member.getValue());
+          }
+          break;
+        case "http2ConnectionWindowSize":
+          if (member.getValue() instanceof Number) {
+            obj.setHttp2ConnectionWindowSize(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "initialSettings":
+          if (member.getValue() instanceof JsonObject) {
+            obj.setInitialSettings(new io.vertx.core.http.Http2Settings((JsonObject)member.getValue()));
+          }
+          break;
+        case "maxChunkSize":
+          if (member.getValue() instanceof Number) {
+            obj.setMaxChunkSize(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "maxHeaderSize":
+          if (member.getValue() instanceof Number) {
+            obj.setMaxHeaderSize(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "maxInitialLineLength":
+          if (member.getValue() instanceof Number) {
+            obj.setMaxInitialLineLength(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "maxWebSocketFrameSize":
+          if (member.getValue() instanceof Number) {
+            obj.setMaxWebSocketFrameSize(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "maxWebSocketMessageSize":
+          if (member.getValue() instanceof Number) {
+            obj.setMaxWebSocketMessageSize(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "maxWebsocketFrameSize":
+          if (member.getValue() instanceof Number) {
+            obj.setMaxWebsocketFrameSize(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "maxWebsocketMessageSize":
+          if (member.getValue() instanceof Number) {
+            obj.setMaxWebsocketMessageSize(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "perFrameWebSocketCompressionSupported":
+          if (member.getValue() instanceof Boolean) {
+            obj.setPerFrameWebSocketCompressionSupported((Boolean)member.getValue());
+          }
+          break;
+        case "perFrameWebsocketCompressionSupported":
+          if (member.getValue() instanceof Boolean) {
+            obj.setPerFrameWebsocketCompressionSupported((Boolean)member.getValue());
+          }
+          break;
+        case "perMessageWebSocketCompressionSupported":
+          if (member.getValue() instanceof Boolean) {
+            obj.setPerMessageWebSocketCompressionSupported((Boolean)member.getValue());
+          }
+          break;
+        case "perMessageWebsocketCompressionSupported":
+          if (member.getValue() instanceof Boolean) {
+            obj.setPerMessageWebsocketCompressionSupported((Boolean)member.getValue());
+          }
+          break;
+        case "webSocketAllowServerNoContext":
+          if (member.getValue() instanceof Boolean) {
+            obj.setWebSocketAllowServerNoContext((Boolean)member.getValue());
+          }
+          break;
+        case "webSocketClosingTimeout":
+          if (member.getValue() instanceof Number) {
+            obj.setWebSocketClosingTimeout(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "webSocketCompressionLevel":
+          if (member.getValue() instanceof Number) {
+            obj.setWebSocketCompressionLevel(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "webSocketPreferredClientNoContext":
+          if (member.getValue() instanceof Boolean) {
+            obj.setWebSocketPreferredClientNoContext((Boolean)member.getValue());
+          }
+          break;
+        case "webSocketSubProtocols":
+          if (member.getValue() instanceof JsonArray) {
+            java.util.ArrayList<java.lang.String> list =  new java.util.ArrayList<>();
+            ((Iterable<Object>)member.getValue()).forEach( item -> {
+              if (item instanceof String)
+                list.add((String)item);
+            });
+            obj.setWebSocketSubProtocols(list);
+          }
+          break;
+        case "websocketAllowServerNoContext":
+          if (member.getValue() instanceof Boolean) {
+            obj.setWebsocketAllowServerNoContext((Boolean)member.getValue());
+          }
+          break;
+        case "websocketCompressionLevel":
+          if (member.getValue() instanceof Number) {
+            obj.setWebsocketCompressionLevel(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "websocketPreferredClientNoContext":
+          if (member.getValue() instanceof Boolean) {
+            obj.setWebsocketPreferredClientNoContext((Boolean)member.getValue());
+          }
+          break;
+        case "websocketSubProtocols":
+          if (member.getValue() instanceof String) {
+            obj.setWebsocketSubProtocols((String)member.getValue());
+          }
+          break;
+      }
+    }
+  }
+
+   static void toJson(HttpServerOptions obj, JsonObject json) {
+    toJson(obj, json.getMap());
+  }
+
+   static void toJson(HttpServerOptions obj, java.util.Map<String, Object> json) {
+    json.put("acceptUnmaskedFrames", obj.isAcceptUnmaskedFrames());
+    if (obj.getAlpnVersions() != null) {
+      JsonArray array = new JsonArray();
+      obj.getAlpnVersions().forEach(item -> array.add(item.name()));
+      json.put("alpnVersions", array);
+    }
+    json.put("compressionLevel", obj.getCompressionLevel());
+    json.put("compressionSupported", obj.isCompressionSupported());
+    json.put("decoderInitialBufferSize", obj.getDecoderInitialBufferSize());
+    json.put("decompressionSupported", obj.isDecompressionSupported());
+    json.put("handle100ContinueAutomatically", obj.isHandle100ContinueAutomatically());
+    json.put("http2ConnectionWindowSize", obj.getHttp2ConnectionWindowSize());
+    if (obj.getInitialSettings() != null) {
+      json.put("initialSettings", obj.getInitialSettings().toJson());
+    }
+    json.put("maxChunkSize", obj.getMaxChunkSize());
+    json.put("maxHeaderSize", obj.getMaxHeaderSize());
+    json.put("maxInitialLineLength", obj.getMaxInitialLineLength());
+    json.put("maxWebSocketFrameSize", obj.getMaxWebSocketFrameSize());
+    json.put("maxWebSocketMessageSize", obj.getMaxWebSocketMessageSize());
+    json.put("maxWebsocketFrameSize", obj.getMaxWebsocketFrameSize());
+    json.put("maxWebsocketMessageSize", obj.getMaxWebsocketMessageSize());
+    json.put("perFrameWebSocketCompressionSupported", obj.getPerFrameWebSocketCompressionSupported());
+    json.put("perFrameWebsocketCompressionSupported", obj.getPerFrameWebsocketCompressionSupported());
+    json.put("perMessageWebSocketCompressionSupported", obj.getPerMessageWebSocketCompressionSupported());
+    json.put("perMessageWebsocketCompressionSupported", obj.getPerMessageWebsocketCompressionSupported());
+    json.put("webSocketAllowServerNoContext", obj.getWebSocketAllowServerNoContext());
+    json.put("webSocketClosingTimeout", obj.getWebSocketClosingTimeout());
+    json.put("webSocketCompressionLevel", obj.getWebSocketCompressionLevel());
+    json.put("webSocketPreferredClientNoContext", obj.getWebSocketPreferredClientNoContext());
+    if (obj.getWebSocketSubProtocols() != null) {
+      JsonArray array = new JsonArray();
+      obj.getWebSocketSubProtocols().forEach(item -> array.add(item));
+      json.put("webSocketSubProtocols", array);
+    }
+    json.put("websocketAllowServerNoContext", obj.getWebsocketAllowServerNoContext());
+    json.put("websocketCompressionLevel", obj.getWebsocketCompressionLevel());
+    json.put("websocketPreferredClientNoContext", obj.getWebsocketPreferredClientNoContext());
+    if (obj.getWebsocketSubProtocols() != null) {
+      json.put("websocketSubProtocols", obj.getWebsocketSubProtocols());
+    }
+  }
+}
diff --git a/src/main/generated/io/vertx/core/http/RequestOptionsConverter.java b/src/main/generated/io/vertx/core/http/RequestOptionsConverter.java
new file mode 100644
--- /dev/null
+++ b/src/main/generated/io/vertx/core/http/RequestOptionsConverter.java
@@ -0,0 +1,65 @@
+package io.vertx.core.http;
+
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.json.JsonArray;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Converter for {@link io.vertx.core.http.RequestOptions}.
+ * NOTE: This class has been automatically generated from the {@link io.vertx.core.http.RequestOptions} original class using Vert.x codegen.
+ */
+public class RequestOptionsConverter {
+
+  public static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, RequestOptions obj) {
+    for (java.util.Map.Entry<String, Object> member : json) {
+      switch (member.getKey()) {
+        case "headers":
+          if (member.getValue() instanceof JsonObject) {
+            ((Iterable<java.util.Map.Entry<String, Object>>)member.getValue()).forEach(entry -> {
+              if (entry.getValue() instanceof String)
+                obj.addHeader(entry.getKey(), (String)entry.getValue());
+            });
+          }
+          break;
+        case "host":
+          if (member.getValue() instanceof String) {
+            obj.setHost((String)member.getValue());
+          }
+          break;
+        case "port":
+          if (member.getValue() instanceof Number) {
+            obj.setPort(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "ssl":
+          if (member.getValue() instanceof Boolean) {
+            obj.setSsl((Boolean)member.getValue());
+          }
+          break;
+        case "uri":
+          if (member.getValue() instanceof String) {
+            obj.setURI((String)member.getValue());
+          }
+          break;
+      }
+    }
+  }
+
+  public static void toJson(RequestOptions obj, JsonObject json) {
+    toJson(obj, json.getMap());
+  }
+
+  public static void toJson(RequestOptions obj, java.util.Map<String, Object> json) {
+    if (obj.getHost() != null) {
+      json.put("host", obj.getHost());
+    }
+    json.put("port", obj.getPort());
+    if (obj.isSsl() != null) {
+      json.put("ssl", obj.isSsl());
+    }
+    if (obj.getURI() != null) {
+      json.put("uri", obj.getURI());
+    }
+  }
+}
diff --git a/src/main/generated/io/vertx/core/http/WebSocketConnectOptionsConverter.java b/src/main/generated/io/vertx/core/http/WebSocketConnectOptionsConverter.java
new file mode 100644
--- /dev/null
+++ b/src/main/generated/io/vertx/core/http/WebSocketConnectOptionsConverter.java
@@ -0,0 +1,50 @@
+package io.vertx.core.http;
+
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.json.JsonArray;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Converter for {@link io.vertx.core.http.WebSocketConnectOptions}.
+ * NOTE: This class has been automatically generated from the {@link io.vertx.core.http.WebSocketConnectOptions} original class using Vert.x codegen.
+ */
+public class WebSocketConnectOptionsConverter {
+
+  public static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, WebSocketConnectOptions obj) {
+    for (java.util.Map.Entry<String, Object> member : json) {
+      switch (member.getKey()) {
+        case "subProtocols":
+          if (member.getValue() instanceof JsonArray) {
+            java.util.ArrayList<java.lang.String> list =  new java.util.ArrayList<>();
+            ((Iterable<Object>)member.getValue()).forEach( item -> {
+              if (item instanceof String)
+                list.add((String)item);
+            });
+            obj.setSubProtocols(list);
+          }
+          break;
+        case "version":
+          if (member.getValue() instanceof String) {
+            obj.setVersion(io.vertx.core.http.WebsocketVersion.valueOf((String)member.getValue()));
+          }
+          break;
+      }
+    }
+  }
+
+  public static void toJson(WebSocketConnectOptions obj, JsonObject json) {
+    toJson(obj, json.getMap());
+  }
+
+  public static void toJson(WebSocketConnectOptions obj, java.util.Map<String, Object> json) {
+    if (obj.getSubProtocols() != null) {
+      JsonArray array = new JsonArray();
+      obj.getSubProtocols().forEach(item -> array.add(item));
+      json.put("subProtocols", array);
+    }
+    if (obj.getVersion() != null) {
+      json.put("version", obj.getVersion().name());
+    }
+  }
+}
diff --git a/src/main/generated/io/vertx/core/metrics/MetricsOptionsConverter.java b/src/main/generated/io/vertx/core/metrics/MetricsOptionsConverter.java
new file mode 100644
--- /dev/null
+++ b/src/main/generated/io/vertx/core/metrics/MetricsOptionsConverter.java
@@ -0,0 +1,33 @@
+package io.vertx.core.metrics;
+
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.json.JsonArray;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Converter for {@link io.vertx.core.metrics.MetricsOptions}.
+ * NOTE: This class has been automatically generated from the {@link io.vertx.core.metrics.MetricsOptions} original class using Vert.x codegen.
+ */
+ class MetricsOptionsConverter {
+
+   static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, MetricsOptions obj) {
+    for (java.util.Map.Entry<String, Object> member : json) {
+      switch (member.getKey()) {
+        case "enabled":
+          if (member.getValue() instanceof Boolean) {
+            obj.setEnabled((Boolean)member.getValue());
+          }
+          break;
+      }
+    }
+  }
+
+   static void toJson(MetricsOptions obj, JsonObject json) {
+    toJson(obj, json.getMap());
+  }
+
+   static void toJson(MetricsOptions obj, java.util.Map<String, Object> json) {
+    json.put("enabled", obj.isEnabled());
+  }
+}
diff --git a/src/main/generated/io/vertx/core/net/ClientOptionsBaseConverter.java b/src/main/generated/io/vertx/core/net/ClientOptionsBaseConverter.java
new file mode 100644
--- /dev/null
+++ b/src/main/generated/io/vertx/core/net/ClientOptionsBaseConverter.java
@@ -0,0 +1,63 @@
+package io.vertx.core.net;
+
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.json.JsonArray;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Converter for {@link io.vertx.core.net.ClientOptionsBase}.
+ * NOTE: This class has been automatically generated from the {@link io.vertx.core.net.ClientOptionsBase} original class using Vert.x codegen.
+ */
+ class ClientOptionsBaseConverter {
+
+   static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, ClientOptionsBase obj) {
+    for (java.util.Map.Entry<String, Object> member : json) {
+      switch (member.getKey()) {
+        case "connectTimeout":
+          if (member.getValue() instanceof Number) {
+            obj.setConnectTimeout(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "localAddress":
+          if (member.getValue() instanceof String) {
+            obj.setLocalAddress((String)member.getValue());
+          }
+          break;
+        case "metricsName":
+          if (member.getValue() instanceof String) {
+            obj.setMetricsName((String)member.getValue());
+          }
+          break;
+        case "proxyOptions":
+          if (member.getValue() instanceof JsonObject) {
+            obj.setProxyOptions(new io.vertx.core.net.ProxyOptions((JsonObject)member.getValue()));
+          }
+          break;
+        case "trustAll":
+          if (member.getValue() instanceof Boolean) {
+            obj.setTrustAll((Boolean)member.getValue());
+          }
+          break;
+      }
+    }
+  }
+
+   static void toJson(ClientOptionsBase obj, JsonObject json) {
+    toJson(obj, json.getMap());
+  }
+
+   static void toJson(ClientOptionsBase obj, java.util.Map<String, Object> json) {
+    json.put("connectTimeout", obj.getConnectTimeout());
+    if (obj.getLocalAddress() != null) {
+      json.put("localAddress", obj.getLocalAddress());
+    }
+    if (obj.getMetricsName() != null) {
+      json.put("metricsName", obj.getMetricsName());
+    }
+    if (obj.getProxyOptions() != null) {
+      json.put("proxyOptions", obj.getProxyOptions().toJson());
+    }
+    json.put("trustAll", obj.isTrustAll());
+  }
+}
diff --git a/src/main/generated/io/vertx/core/net/JksOptionsConverter.java b/src/main/generated/io/vertx/core/net/JksOptionsConverter.java
new file mode 100644
--- /dev/null
+++ b/src/main/generated/io/vertx/core/net/JksOptionsConverter.java
@@ -0,0 +1,51 @@
+package io.vertx.core.net;
+
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.json.JsonArray;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Converter for {@link io.vertx.core.net.JksOptions}.
+ * NOTE: This class has been automatically generated from the {@link io.vertx.core.net.JksOptions} original class using Vert.x codegen.
+ */
+public class JksOptionsConverter {
+
+  public static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, JksOptions obj) {
+    for (java.util.Map.Entry<String, Object> member : json) {
+      switch (member.getKey()) {
+        case "password":
+          if (member.getValue() instanceof String) {
+            obj.setPassword((String)member.getValue());
+          }
+          break;
+        case "path":
+          if (member.getValue() instanceof String) {
+            obj.setPath((String)member.getValue());
+          }
+          break;
+        case "value":
+          if (member.getValue() instanceof String) {
+            obj.setValue(io.vertx.core.buffer.Buffer.buffer(java.util.Base64.getDecoder().decode((String)member.getValue())));
+          }
+          break;
+      }
+    }
+  }
+
+  public static void toJson(JksOptions obj, JsonObject json) {
+    toJson(obj, json.getMap());
+  }
+
+  public static void toJson(JksOptions obj, java.util.Map<String, Object> json) {
+    if (obj.getPassword() != null) {
+      json.put("password", obj.getPassword());
+    }
+    if (obj.getPath() != null) {
+      json.put("path", obj.getPath());
+    }
+    if (obj.getValue() != null) {
+      json.put("value", java.util.Base64.getEncoder().encodeToString(obj.getValue().getBytes()));
+    }
+  }
+}
diff --git a/src/main/generated/io/vertx/core/net/KeyStoreOptionsConverter.java b/src/main/generated/io/vertx/core/net/KeyStoreOptionsConverter.java
new file mode 100644
--- /dev/null
+++ b/src/main/generated/io/vertx/core/net/KeyStoreOptionsConverter.java
@@ -0,0 +1,67 @@
+package io.vertx.core.net;
+
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.json.JsonArray;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Converter for {@link io.vertx.core.net.KeyStoreOptions}.
+ * NOTE: This class has been automatically generated from the {@link io.vertx.core.net.KeyStoreOptions} original class using Vert.x codegen.
+ */
+public class KeyStoreOptionsConverter {
+
+  public static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, KeyStoreOptions obj) {
+    for (java.util.Map.Entry<String, Object> member : json) {
+      switch (member.getKey()) {
+        case "password":
+          if (member.getValue() instanceof String) {
+            obj.setPassword((String)member.getValue());
+          }
+          break;
+        case "path":
+          if (member.getValue() instanceof String) {
+            obj.setPath((String)member.getValue());
+          }
+          break;
+        case "provider":
+          if (member.getValue() instanceof String) {
+            obj.setProvider((String)member.getValue());
+          }
+          break;
+        case "type":
+          if (member.getValue() instanceof String) {
+            obj.setType((String)member.getValue());
+          }
+          break;
+        case "value":
+          if (member.getValue() instanceof String) {
+            obj.setValue(io.vertx.core.buffer.Buffer.buffer(java.util.Base64.getDecoder().decode((String)member.getValue())));
+          }
+          break;
+      }
+    }
+  }
+
+  public static void toJson(KeyStoreOptions obj, JsonObject json) {
+    toJson(obj, json.getMap());
+  }
+
+  public static void toJson(KeyStoreOptions obj, java.util.Map<String, Object> json) {
+    if (obj.getPassword() != null) {
+      json.put("password", obj.getPassword());
+    }
+    if (obj.getPath() != null) {
+      json.put("path", obj.getPath());
+    }
+    if (obj.getProvider() != null) {
+      json.put("provider", obj.getProvider());
+    }
+    if (obj.getType() != null) {
+      json.put("type", obj.getType());
+    }
+    if (obj.getValue() != null) {
+      json.put("value", java.util.Base64.getEncoder().encodeToString(obj.getValue().getBytes()));
+    }
+  }
+}
diff --git a/src/main/generated/io/vertx/core/net/NetClientOptionsConverter.java b/src/main/generated/io/vertx/core/net/NetClientOptionsConverter.java
new file mode 100644
--- /dev/null
+++ b/src/main/generated/io/vertx/core/net/NetClientOptionsConverter.java
@@ -0,0 +1,47 @@
+package io.vertx.core.net;
+
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.json.JsonArray;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Converter for {@link io.vertx.core.net.NetClientOptions}.
+ * NOTE: This class has been automatically generated from the {@link io.vertx.core.net.NetClientOptions} original class using Vert.x codegen.
+ */
+ class NetClientOptionsConverter {
+
+   static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, NetClientOptions obj) {
+    for (java.util.Map.Entry<String, Object> member : json) {
+      switch (member.getKey()) {
+        case "hostnameVerificationAlgorithm":
+          if (member.getValue() instanceof String) {
+            obj.setHostnameVerificationAlgorithm((String)member.getValue());
+          }
+          break;
+        case "reconnectAttempts":
+          if (member.getValue() instanceof Number) {
+            obj.setReconnectAttempts(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "reconnectInterval":
+          if (member.getValue() instanceof Number) {
+            obj.setReconnectInterval(((Number)member.getValue()).longValue());
+          }
+          break;
+      }
+    }
+  }
+
+   static void toJson(NetClientOptions obj, JsonObject json) {
+    toJson(obj, json.getMap());
+  }
+
+   static void toJson(NetClientOptions obj, java.util.Map<String, Object> json) {
+    if (obj.getHostnameVerificationAlgorithm() != null) {
+      json.put("hostnameVerificationAlgorithm", obj.getHostnameVerificationAlgorithm());
+    }
+    json.put("reconnectAttempts", obj.getReconnectAttempts());
+    json.put("reconnectInterval", obj.getReconnectInterval());
+  }
+}
diff --git a/src/main/generated/io/vertx/core/net/NetServerOptionsConverter.java b/src/main/generated/io/vertx/core/net/NetServerOptionsConverter.java
new file mode 100644
--- /dev/null
+++ b/src/main/generated/io/vertx/core/net/NetServerOptionsConverter.java
@@ -0,0 +1,67 @@
+package io.vertx.core.net;
+
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.json.JsonArray;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Converter for {@link io.vertx.core.net.NetServerOptions}.
+ * NOTE: This class has been automatically generated from the {@link io.vertx.core.net.NetServerOptions} original class using Vert.x codegen.
+ */
+ class NetServerOptionsConverter {
+
+   static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, NetServerOptions obj) {
+    for (java.util.Map.Entry<String, Object> member : json) {
+      switch (member.getKey()) {
+        case "acceptBacklog":
+          if (member.getValue() instanceof Number) {
+            obj.setAcceptBacklog(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "clientAuth":
+          if (member.getValue() instanceof String) {
+            obj.setClientAuth(io.vertx.core.http.ClientAuth.valueOf((String)member.getValue()));
+          }
+          break;
+        case "clientAuthRequired":
+          if (member.getValue() instanceof Boolean) {
+            obj.setClientAuthRequired((Boolean)member.getValue());
+          }
+          break;
+        case "host":
+          if (member.getValue() instanceof String) {
+            obj.setHost((String)member.getValue());
+          }
+          break;
+        case "port":
+          if (member.getValue() instanceof Number) {
+            obj.setPort(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "sni":
+          if (member.getValue() instanceof Boolean) {
+            obj.setSni((Boolean)member.getValue());
+          }
+          break;
+      }
+    }
+  }
+
+   static void toJson(NetServerOptions obj, JsonObject json) {
+    toJson(obj, json.getMap());
+  }
+
+   static void toJson(NetServerOptions obj, java.util.Map<String, Object> json) {
+    json.put("acceptBacklog", obj.getAcceptBacklog());
+    if (obj.getClientAuth() != null) {
+      json.put("clientAuth", obj.getClientAuth().name());
+    }
+    json.put("clientAuthRequired", obj.isClientAuthRequired());
+    if (obj.getHost() != null) {
+      json.put("host", obj.getHost());
+    }
+    json.put("port", obj.getPort());
+    json.put("sni", obj.isSni());
+  }
+}
diff --git a/src/main/generated/io/vertx/core/net/NetworkOptionsConverter.java b/src/main/generated/io/vertx/core/net/NetworkOptionsConverter.java
new file mode 100644
--- /dev/null
+++ b/src/main/generated/io/vertx/core/net/NetworkOptionsConverter.java
@@ -0,0 +1,63 @@
+package io.vertx.core.net;
+
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.json.JsonArray;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Converter for {@link io.vertx.core.net.NetworkOptions}.
+ * NOTE: This class has been automatically generated from the {@link io.vertx.core.net.NetworkOptions} original class using Vert.x codegen.
+ */
+ class NetworkOptionsConverter {
+
+   static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, NetworkOptions obj) {
+    for (java.util.Map.Entry<String, Object> member : json) {
+      switch (member.getKey()) {
+        case "logActivity":
+          if (member.getValue() instanceof Boolean) {
+            obj.setLogActivity((Boolean)member.getValue());
+          }
+          break;
+        case "receiveBufferSize":
+          if (member.getValue() instanceof Number) {
+            obj.setReceiveBufferSize(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "reuseAddress":
+          if (member.getValue() instanceof Boolean) {
+            obj.setReuseAddress((Boolean)member.getValue());
+          }
+          break;
+        case "reusePort":
+          if (member.getValue() instanceof Boolean) {
+            obj.setReusePort((Boolean)member.getValue());
+          }
+          break;
+        case "sendBufferSize":
+          if (member.getValue() instanceof Number) {
+            obj.setSendBufferSize(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "trafficClass":
+          if (member.getValue() instanceof Number) {
+            obj.setTrafficClass(((Number)member.getValue()).intValue());
+          }
+          break;
+      }
+    }
+  }
+
+   static void toJson(NetworkOptions obj, JsonObject json) {
+    toJson(obj, json.getMap());
+  }
+
+   static void toJson(NetworkOptions obj, java.util.Map<String, Object> json) {
+    json.put("logActivity", obj.getLogActivity());
+    json.put("receiveBufferSize", obj.getReceiveBufferSize());
+    json.put("reuseAddress", obj.isReuseAddress());
+    json.put("reusePort", obj.isReusePort());
+    json.put("sendBufferSize", obj.getSendBufferSize());
+    json.put("trafficClass", obj.getTrafficClass());
+  }
+}
diff --git a/src/main/generated/io/vertx/core/net/OpenSSLEngineOptionsConverter.java b/src/main/generated/io/vertx/core/net/OpenSSLEngineOptionsConverter.java
new file mode 100644
--- /dev/null
+++ b/src/main/generated/io/vertx/core/net/OpenSSLEngineOptionsConverter.java
@@ -0,0 +1,33 @@
+package io.vertx.core.net;
+
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.json.JsonArray;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Converter for {@link io.vertx.core.net.OpenSSLEngineOptions}.
+ * NOTE: This class has been automatically generated from the {@link io.vertx.core.net.OpenSSLEngineOptions} original class using Vert.x codegen.
+ */
+ class OpenSSLEngineOptionsConverter {
+
+   static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, OpenSSLEngineOptions obj) {
+    for (java.util.Map.Entry<String, Object> member : json) {
+      switch (member.getKey()) {
+        case "sessionCacheEnabled":
+          if (member.getValue() instanceof Boolean) {
+            obj.setSessionCacheEnabled((Boolean)member.getValue());
+          }
+          break;
+      }
+    }
+  }
+
+   static void toJson(OpenSSLEngineOptions obj, JsonObject json) {
+    toJson(obj, json.getMap());
+  }
+
+   static void toJson(OpenSSLEngineOptions obj, java.util.Map<String, Object> json) {
+    json.put("sessionCacheEnabled", obj.isSessionCacheEnabled());
+  }
+}
diff --git a/src/main/generated/io/vertx/core/net/PemKeyCertOptionsConverter.java b/src/main/generated/io/vertx/core/net/PemKeyCertOptionsConverter.java
new file mode 100644
--- /dev/null
+++ b/src/main/generated/io/vertx/core/net/PemKeyCertOptionsConverter.java
@@ -0,0 +1,107 @@
+package io.vertx.core.net;
+
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.json.JsonArray;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Converter for {@link io.vertx.core.net.PemKeyCertOptions}.
+ * NOTE: This class has been automatically generated from the {@link io.vertx.core.net.PemKeyCertOptions} original class using Vert.x codegen.
+ */
+ class PemKeyCertOptionsConverter {
+
+   static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, PemKeyCertOptions obj) {
+    for (java.util.Map.Entry<String, Object> member : json) {
+      switch (member.getKey()) {
+        case "certPath":
+          if (member.getValue() instanceof String) {
+            obj.setCertPath((String)member.getValue());
+          }
+          break;
+        case "certPaths":
+          if (member.getValue() instanceof JsonArray) {
+            java.util.ArrayList<java.lang.String> list =  new java.util.ArrayList<>();
+            ((Iterable<Object>)member.getValue()).forEach( item -> {
+              if (item instanceof String)
+                list.add((String)item);
+            });
+            obj.setCertPaths(list);
+          }
+          break;
+        case "certValue":
+          if (member.getValue() instanceof String) {
+            obj.setCertValue(io.vertx.core.buffer.Buffer.buffer(java.util.Base64.getDecoder().decode((String)member.getValue())));
+          }
+          break;
+        case "certValues":
+          if (member.getValue() instanceof JsonArray) {
+            java.util.ArrayList<io.vertx.core.buffer.Buffer> list =  new java.util.ArrayList<>();
+            ((Iterable<Object>)member.getValue()).forEach( item -> {
+              if (item instanceof String)
+                list.add(io.vertx.core.buffer.Buffer.buffer(java.util.Base64.getDecoder().decode((String)item)));
+            });
+            obj.setCertValues(list);
+          }
+          break;
+        case "keyPath":
+          if (member.getValue() instanceof String) {
+            obj.setKeyPath((String)member.getValue());
+          }
+          break;
+        case "keyPaths":
+          if (member.getValue() instanceof JsonArray) {
+            java.util.ArrayList<java.lang.String> list =  new java.util.ArrayList<>();
+            ((Iterable<Object>)member.getValue()).forEach( item -> {
+              if (item instanceof String)
+                list.add((String)item);
+            });
+            obj.setKeyPaths(list);
+          }
+          break;
+        case "keyValue":
+          if (member.getValue() instanceof String) {
+            obj.setKeyValue(io.vertx.core.buffer.Buffer.buffer(java.util.Base64.getDecoder().decode((String)member.getValue())));
+          }
+          break;
+        case "keyValues":
+          if (member.getValue() instanceof JsonArray) {
+            java.util.ArrayList<io.vertx.core.buffer.Buffer> list =  new java.util.ArrayList<>();
+            ((Iterable<Object>)member.getValue()).forEach( item -> {
+              if (item instanceof String)
+                list.add(io.vertx.core.buffer.Buffer.buffer(java.util.Base64.getDecoder().decode((String)item)));
+            });
+            obj.setKeyValues(list);
+          }
+          break;
+      }
+    }
+  }
+
+   static void toJson(PemKeyCertOptions obj, JsonObject json) {
+    toJson(obj, json.getMap());
+  }
+
+   static void toJson(PemKeyCertOptions obj, java.util.Map<String, Object> json) {
+    if (obj.getCertPaths() != null) {
+      JsonArray array = new JsonArray();
+      obj.getCertPaths().forEach(item -> array.add(item));
+      json.put("certPaths", array);
+    }
+    if (obj.getCertValues() != null) {
+      JsonArray array = new JsonArray();
+      obj.getCertValues().forEach(item -> array.add(java.util.Base64.getEncoder().encodeToString(item.getBytes())));
+      json.put("certValues", array);
+    }
+    if (obj.getKeyPaths() != null) {
+      JsonArray array = new JsonArray();
+      obj.getKeyPaths().forEach(item -> array.add(item));
+      json.put("keyPaths", array);
+    }
+    if (obj.getKeyValues() != null) {
+      JsonArray array = new JsonArray();
+      obj.getKeyValues().forEach(item -> array.add(java.util.Base64.getEncoder().encodeToString(item.getBytes())));
+      json.put("keyValues", array);
+    }
+  }
+}
diff --git a/src/main/generated/io/vertx/core/net/PemTrustOptionsConverter.java b/src/main/generated/io/vertx/core/net/PemTrustOptionsConverter.java
new file mode 100644
--- /dev/null
+++ b/src/main/generated/io/vertx/core/net/PemTrustOptionsConverter.java
@@ -0,0 +1,53 @@
+package io.vertx.core.net;
+
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.json.JsonArray;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Converter for {@link io.vertx.core.net.PemTrustOptions}.
+ * NOTE: This class has been automatically generated from the {@link io.vertx.core.net.PemTrustOptions} original class using Vert.x codegen.
+ */
+ class PemTrustOptionsConverter {
+
+   static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, PemTrustOptions obj) {
+    for (java.util.Map.Entry<String, Object> member : json) {
+      switch (member.getKey()) {
+        case "certPaths":
+          if (member.getValue() instanceof JsonArray) {
+            ((Iterable<Object>)member.getValue()).forEach( item -> {
+              if (item instanceof String)
+                obj.addCertPath((String)item);
+            });
+          }
+          break;
+        case "certValues":
+          if (member.getValue() instanceof JsonArray) {
+            ((Iterable<Object>)member.getValue()).forEach( item -> {
+              if (item instanceof String)
+                obj.addCertValue(io.vertx.core.buffer.Buffer.buffer(java.util.Base64.getDecoder().decode((String)item)));
+            });
+          }
+          break;
+      }
+    }
+  }
+
+   static void toJson(PemTrustOptions obj, JsonObject json) {
+    toJson(obj, json.getMap());
+  }
+
+   static void toJson(PemTrustOptions obj, java.util.Map<String, Object> json) {
+    if (obj.getCertPaths() != null) {
+      JsonArray array = new JsonArray();
+      obj.getCertPaths().forEach(item -> array.add(item));
+      json.put("certPaths", array);
+    }
+    if (obj.getCertValues() != null) {
+      JsonArray array = new JsonArray();
+      obj.getCertValues().forEach(item -> array.add(java.util.Base64.getEncoder().encodeToString(item.getBytes())));
+      json.put("certValues", array);
+    }
+  }
+}
diff --git a/src/main/generated/io/vertx/core/net/PfxOptionsConverter.java b/src/main/generated/io/vertx/core/net/PfxOptionsConverter.java
new file mode 100644
--- /dev/null
+++ b/src/main/generated/io/vertx/core/net/PfxOptionsConverter.java
@@ -0,0 +1,51 @@
+package io.vertx.core.net;
+
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.json.JsonArray;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Converter for {@link io.vertx.core.net.PfxOptions}.
+ * NOTE: This class has been automatically generated from the {@link io.vertx.core.net.PfxOptions} original class using Vert.x codegen.
+ */
+ class PfxOptionsConverter {
+
+   static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, PfxOptions obj) {
+    for (java.util.Map.Entry<String, Object> member : json) {
+      switch (member.getKey()) {
+        case "password":
+          if (member.getValue() instanceof String) {
+            obj.setPassword((String)member.getValue());
+          }
+          break;
+        case "path":
+          if (member.getValue() instanceof String) {
+            obj.setPath((String)member.getValue());
+          }
+          break;
+        case "value":
+          if (member.getValue() instanceof String) {
+            obj.setValue(io.vertx.core.buffer.Buffer.buffer(java.util.Base64.getDecoder().decode((String)member.getValue())));
+          }
+          break;
+      }
+    }
+  }
+
+   static void toJson(PfxOptions obj, JsonObject json) {
+    toJson(obj, json.getMap());
+  }
+
+   static void toJson(PfxOptions obj, java.util.Map<String, Object> json) {
+    if (obj.getPassword() != null) {
+      json.put("password", obj.getPassword());
+    }
+    if (obj.getPath() != null) {
+      json.put("path", obj.getPath());
+    }
+    if (obj.getValue() != null) {
+      json.put("value", java.util.Base64.getEncoder().encodeToString(obj.getValue().getBytes()));
+    }
+  }
+}
diff --git a/src/main/generated/io/vertx/core/net/ProxyOptionsConverter.java b/src/main/generated/io/vertx/core/net/ProxyOptionsConverter.java
new file mode 100644
--- /dev/null
+++ b/src/main/generated/io/vertx/core/net/ProxyOptionsConverter.java
@@ -0,0 +1,65 @@
+package io.vertx.core.net;
+
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.json.JsonArray;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Converter for {@link io.vertx.core.net.ProxyOptions}.
+ * NOTE: This class has been automatically generated from the {@link io.vertx.core.net.ProxyOptions} original class using Vert.x codegen.
+ */
+ class ProxyOptionsConverter {
+
+   static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, ProxyOptions obj) {
+    for (java.util.Map.Entry<String, Object> member : json) {
+      switch (member.getKey()) {
+        case "host":
+          if (member.getValue() instanceof String) {
+            obj.setHost((String)member.getValue());
+          }
+          break;
+        case "password":
+          if (member.getValue() instanceof String) {
+            obj.setPassword((String)member.getValue());
+          }
+          break;
+        case "port":
+          if (member.getValue() instanceof Number) {
+            obj.setPort(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "type":
+          if (member.getValue() instanceof String) {
+            obj.setType(io.vertx.core.net.ProxyType.valueOf((String)member.getValue()));
+          }
+          break;
+        case "username":
+          if (member.getValue() instanceof String) {
+            obj.setUsername((String)member.getValue());
+          }
+          break;
+      }
+    }
+  }
+
+   static void toJson(ProxyOptions obj, JsonObject json) {
+    toJson(obj, json.getMap());
+  }
+
+   static void toJson(ProxyOptions obj, java.util.Map<String, Object> json) {
+    if (obj.getHost() != null) {
+      json.put("host", obj.getHost());
+    }
+    if (obj.getPassword() != null) {
+      json.put("password", obj.getPassword());
+    }
+    json.put("port", obj.getPort());
+    if (obj.getType() != null) {
+      json.put("type", obj.getType().name());
+    }
+    if (obj.getUsername() != null) {
+      json.put("username", obj.getUsername());
+    }
+  }
+}
diff --git a/src/main/generated/io/vertx/core/net/TCPSSLOptionsConverter.java b/src/main/generated/io/vertx/core/net/TCPSSLOptionsConverter.java
new file mode 100644
--- /dev/null
+++ b/src/main/generated/io/vertx/core/net/TCPSSLOptionsConverter.java
@@ -0,0 +1,227 @@
+package io.vertx.core.net;
+
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.json.JsonArray;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Converter for {@link io.vertx.core.net.TCPSSLOptions}.
+ * NOTE: This class has been automatically generated from the {@link io.vertx.core.net.TCPSSLOptions} original class using Vert.x codegen.
+ */
+ class TCPSSLOptionsConverter {
+
+   static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, TCPSSLOptions obj) {
+    for (java.util.Map.Entry<String, Object> member : json) {
+      switch (member.getKey()) {
+        case "crlPaths":
+          if (member.getValue() instanceof JsonArray) {
+            ((Iterable<Object>)member.getValue()).forEach( item -> {
+              if (item instanceof String)
+                obj.addCrlPath((String)item);
+            });
+          }
+          break;
+        case "crlValues":
+          if (member.getValue() instanceof JsonArray) {
+            ((Iterable<Object>)member.getValue()).forEach( item -> {
+              if (item instanceof String)
+                obj.addCrlValue(io.vertx.core.buffer.Buffer.buffer(java.util.Base64.getDecoder().decode((String)item)));
+            });
+          }
+          break;
+        case "enabledCipherSuites":
+          if (member.getValue() instanceof JsonArray) {
+            ((Iterable<Object>)member.getValue()).forEach( item -> {
+              if (item instanceof String)
+                obj.addEnabledCipherSuite((String)item);
+            });
+          }
+          break;
+        case "enabledSecureTransportProtocols":
+          if (member.getValue() instanceof JsonArray) {
+            java.util.LinkedHashSet<java.lang.String> list =  new java.util.LinkedHashSet<>();
+            ((Iterable<Object>)member.getValue()).forEach( item -> {
+              if (item instanceof String)
+                list.add((String)item);
+            });
+            obj.setEnabledSecureTransportProtocols(list);
+          }
+          break;
+        case "idleTimeout":
+          if (member.getValue() instanceof Number) {
+            obj.setIdleTimeout(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "idleTimeoutUnit":
+          if (member.getValue() instanceof String) {
+            obj.setIdleTimeoutUnit(java.util.concurrent.TimeUnit.valueOf((String)member.getValue()));
+          }
+          break;
+        case "jdkSslEngineOptions":
+          if (member.getValue() instanceof JsonObject) {
+            obj.setJdkSslEngineOptions(new io.vertx.core.net.JdkSSLEngineOptions((JsonObject)member.getValue()));
+          }
+          break;
+        case "keyStoreOptions":
+          if (member.getValue() instanceof JsonObject) {
+            obj.setKeyStoreOptions(new io.vertx.core.net.JksOptions((JsonObject)member.getValue()));
+          }
+          break;
+        case "openSslEngineOptions":
+          if (member.getValue() instanceof JsonObject) {
+            obj.setOpenSslEngineOptions(new io.vertx.core.net.OpenSSLEngineOptions((JsonObject)member.getValue()));
+          }
+          break;
+        case "pemKeyCertOptions":
+          if (member.getValue() instanceof JsonObject) {
+            obj.setPemKeyCertOptions(new io.vertx.core.net.PemKeyCertOptions((JsonObject)member.getValue()));
+          }
+          break;
+        case "pemTrustOptions":
+          if (member.getValue() instanceof JsonObject) {
+            obj.setPemTrustOptions(new io.vertx.core.net.PemTrustOptions((JsonObject)member.getValue()));
+          }
+          break;
+        case "pfxKeyCertOptions":
+          if (member.getValue() instanceof JsonObject) {
+            obj.setPfxKeyCertOptions(new io.vertx.core.net.PfxOptions((JsonObject)member.getValue()));
+          }
+          break;
+        case "pfxTrustOptions":
+          if (member.getValue() instanceof JsonObject) {
+            obj.setPfxTrustOptions(new io.vertx.core.net.PfxOptions((JsonObject)member.getValue()));
+          }
+          break;
+        case "soLinger":
+          if (member.getValue() instanceof Number) {
+            obj.setSoLinger(((Number)member.getValue()).intValue());
+          }
+          break;
+        case "ssl":
+          if (member.getValue() instanceof Boolean) {
+            obj.setSsl((Boolean)member.getValue());
+          }
+          break;
+        case "sslHandshakeTimeout":
+          if (member.getValue() instanceof Number) {
+            obj.setSslHandshakeTimeout(((Number)member.getValue()).longValue());
+          }
+          break;
+        case "sslHandshakeTimeoutUnit":
+          if (member.getValue() instanceof String) {
+            obj.setSslHandshakeTimeoutUnit(java.util.concurrent.TimeUnit.valueOf((String)member.getValue()));
+          }
+          break;
+        case "tcpCork":
+          if (member.getValue() instanceof Boolean) {
+            obj.setTcpCork((Boolean)member.getValue());
+          }
+          break;
+        case "tcpFastOpen":
+          if (member.getValue() instanceof Boolean) {
+            obj.setTcpFastOpen((Boolean)member.getValue());
+          }
+          break;
+        case "tcpKeepAlive":
+          if (member.getValue() instanceof Boolean) {
+            obj.setTcpKeepAlive((Boolean)member.getValue());
+          }
+          break;
+        case "tcpNoDelay":
+          if (member.getValue() instanceof Boolean) {
+            obj.setTcpNoDelay((Boolean)member.getValue());
+          }
+          break;
+        case "tcpQuickAck":
+          if (member.getValue() instanceof Boolean) {
+            obj.setTcpQuickAck((Boolean)member.getValue());
+          }
+          break;
+        case "trustStoreOptions":
+          if (member.getValue() instanceof JsonObject) {
+            obj.setTrustStoreOptions(new io.vertx.core.net.JksOptions((JsonObject)member.getValue()));
+          }
+          break;
+        case "useAlpn":
+          if (member.getValue() instanceof Boolean) {
+            obj.setUseAlpn((Boolean)member.getValue());
+          }
+          break;
+        case "usePooledBuffers":
+          if (member.getValue() instanceof Boolean) {
+            obj.setUsePooledBuffers((Boolean)member.getValue());
+          }
+          break;
+      }
+    }
+  }
+
+   static void toJson(TCPSSLOptions obj, JsonObject json) {
+    toJson(obj, json.getMap());
+  }
+
+   static void toJson(TCPSSLOptions obj, java.util.Map<String, Object> json) {
+    if (obj.getCrlPaths() != null) {
+      JsonArray array = new JsonArray();
+      obj.getCrlPaths().forEach(item -> array.add(item));
+      json.put("crlPaths", array);
+    }
+    if (obj.getCrlValues() != null) {
+      JsonArray array = new JsonArray();
+      obj.getCrlValues().forEach(item -> array.add(java.util.Base64.getEncoder().encodeToString(item.getBytes())));
+      json.put("crlValues", array);
+    }
+    if (obj.getEnabledCipherSuites() != null) {
+      JsonArray array = new JsonArray();
+      obj.getEnabledCipherSuites().forEach(item -> array.add(item));
+      json.put("enabledCipherSuites", array);
+    }
+    if (obj.getEnabledSecureTransportProtocols() != null) {
+      JsonArray array = new JsonArray();
+      obj.getEnabledSecureTransportProtocols().forEach(item -> array.add(item));
+      json.put("enabledSecureTransportProtocols", array);
+    }
+    json.put("idleTimeout", obj.getIdleTimeout());
+    if (obj.getIdleTimeoutUnit() != null) {
+      json.put("idleTimeoutUnit", obj.getIdleTimeoutUnit().name());
+    }
+    if (obj.getJdkSslEngineOptions() != null) {
+      json.put("jdkSslEngineOptions", obj.getJdkSslEngineOptions().toJson());
+    }
+    if (obj.getKeyStoreOptions() != null) {
+      json.put("keyStoreOptions", obj.getKeyStoreOptions().toJson());
+    }
+    if (obj.getOpenSslEngineOptions() != null) {
+      json.put("openSslEngineOptions", obj.getOpenSslEngineOptions().toJson());
+    }
+    if (obj.getPemKeyCertOptions() != null) {
+      json.put("pemKeyCertOptions", obj.getPemKeyCertOptions().toJson());
+    }
+    if (obj.getPemTrustOptions() != null) {
+      json.put("pemTrustOptions", obj.getPemTrustOptions().toJson());
+    }
+    if (obj.getPfxKeyCertOptions() != null) {
+      json.put("pfxKeyCertOptions", obj.getPfxKeyCertOptions().toJson());
+    }
+    if (obj.getPfxTrustOptions() != null) {
+      json.put("pfxTrustOptions", obj.getPfxTrustOptions().toJson());
+    }
+    json.put("soLinger", obj.getSoLinger());
+    json.put("ssl", obj.isSsl());
+    json.put("sslHandshakeTimeout", obj.getSslHandshakeTimeout());
+    if (obj.getSslHandshakeTimeoutUnit() != null) {
+      json.put("sslHandshakeTimeoutUnit", obj.getSslHandshakeTimeoutUnit().name());
+    }
+    json.put("tcpCork", obj.isTcpCork());
+    json.put("tcpFastOpen", obj.isTcpFastOpen());
+    json.put("tcpKeepAlive", obj.isTcpKeepAlive());
+    json.put("tcpNoDelay", obj.isTcpNoDelay());
+    json.put("tcpQuickAck", obj.isTcpQuickAck());
+    if (obj.getTrustStoreOptions() != null) {
+      json.put("trustStoreOptions", obj.getTrustStoreOptions().toJson());
+    }
+    json.put("useAlpn", obj.isUseAlpn());
+    json.put("usePooledBuffers", obj.isUsePooledBuffers());
+  }
+}
diff --git a/src/main/java/io/vertx/core/http/HttpClientOptions.java b/src/main/java/io/vertx/core/http/HttpClientOptions.java
--- a/src/main/java/io/vertx/core/http/HttpClientOptions.java
+++ b/src/main/java/io/vertx/core/http/HttpClientOptions.java
@@ -193,9 +193,9 @@ public class HttpClientOptions extends ClientOptionsBase {
   public static final int DEFAULT_POOL_CLEANER_PERIOD = 1000;
 
   /**
-   * Default WebSocket closing timeout = 10000 ms (10 second)
+   * Default WebSocket closing timeout = 10 second
    */
-  public static final int DEFAULT_WEBSOCKET_CLOSING_TIMEOUT = 10_000;
+  public static final int DEFAULT_WEBSOCKET_CLOSING_TIMEOUT = 10;
 
   private boolean verifyHost = true;
   private int maxPoolSize;
@@ -1383,7 +1383,9 @@ public int getWebSocketClosingTimeout() {
    * <p> When a WebSocket is closed, the server should close the TCP connection. This timeout will close
    * the TCP connection on the client when it expires.
    *
-   * <p> Set {@code 0L} or a negative value to disable.
+   * <p> Set to {@code 0L} closes the TCP connection immediately after receiving the close frame.
+   *
+   * <p> Set to a negative value to disable it.
    *
    * @param webSocketClosingTimeout the timeout is seconds
    * @return a reference to this, so the API can be used fluently
diff --git a/src/main/java/io/vertx/core/http/HttpServerOptions.java b/src/main/java/io/vertx/core/http/HttpServerOptions.java
--- a/src/main/java/io/vertx/core/http/HttpServerOptions.java
+++ b/src/main/java/io/vertx/core/http/HttpServerOptions.java
@@ -104,17 +104,17 @@ public class HttpServerOptions extends NetServerOptions {
    * Default initial buffer size for HttpObjectDecoder = 128 bytes
    */
   public static final int DEFAULT_DECODER_INITIAL_BUFFER_SIZE = 128;
-  
+
   /**
    * Default support for WebSockets per-frame deflate compression extension = {@code true}
    */
   public static final boolean DEFAULT_PER_FRAME_WEBSOCKET_COMPRESSION_SUPPORTED = true;
-  
+
   /**
    * Default support for WebSockets per-message deflate compression extension = {@code true}
    */
   public static final boolean DEFAULT_PER_MESSAGE_WEBSOCKET_COMPRESSION_SUPPORTED = true;
-  
+
   /**
    * Default WebSocket deflate compression level = 6
    */
@@ -130,6 +130,11 @@ public class HttpServerOptions extends NetServerOptions {
    */
   public static final boolean DEFAULT_WEBSOCKET_PREFERRED_CLIENT_NO_CONTEXT = false;
 
+  /**
+   * Default WebSocket closing timeout = 10 second)
+   */
+  public static final int DEFAULT_WEBSOCKET_CLOSING_TIMEOUT = 10;
+
   private boolean compressionSupported;
   private int compressionLevel;
   private int maxWebSocketFrameSize;
@@ -150,6 +155,7 @@ public class HttpServerOptions extends NetServerOptions {
   private int webSocketCompressionLevel;
   private boolean webSocketAllowServerNoContext;
   private boolean webSocketPreferredClientNoContext;
+  private int webSocketClosingTimeout;
 
   /**
    * Default constructor
@@ -187,6 +193,7 @@ public HttpServerOptions(HttpServerOptions other) {
     this.webSocketCompressionLevel = other.webSocketCompressionLevel;
     this.webSocketPreferredClientNoContext = other.webSocketPreferredClientNoContext;
     this.webSocketAllowServerNoContext = other.webSocketAllowServerNoContext;
+    this.webSocketClosingTimeout = other.webSocketClosingTimeout;
   }
 
   /**
@@ -232,6 +239,7 @@ private void init() {
     webSocketCompressionLevel = DEFAULT_WEBSOCKET_COMPRESSION_LEVEL;
     webSocketPreferredClientNoContext = DEFAULT_WEBSOCKET_PREFERRED_CLIENT_NO_CONTEXT;
     webSocketAllowServerNoContext = DEFAULT_WEBSOCKET_ALLOW_SERVER_NO_CONTEXT;
+    webSocketClosingTimeout = DEFAULT_WEBSOCKET_CLOSING_TIMEOUT;
   }
 
   @Override
@@ -1056,7 +1064,35 @@ public boolean getWebsocketPreferredClientNoContext() {
   public boolean getWebSocketPreferredClientNoContext() {
     return this.webSocketPreferredClientNoContext;
   }
-  
+
+  /**
+   * @return the amount of time (in seconds) a client WebSocket will wait until it closes TCP connection after receiving a close frame
+   */
+  public int getWebSocketClosingTimeout() {
+    return webSocketClosingTimeout;
+  }
+
+  /**
+   * Set the amount of time a server WebSocket will wait until it closes the TCP connection
+   * after sending a close frame.
+   *
+   * <p> When a server closes a WebSocket, it should wait the client close frame to close the TCP connection.
+   * This timeout will close the TCP connection on the server when it expires. When the TCP
+   * connection is closed receiving the close frame, the {@link WebSocket#exceptionHandler} instead
+   * of the {@link WebSocket#endHandler} will be called.
+   *
+   * <p> Set to {@code 0L} closes the TCP connection immediately after sending the close frame.
+   *
+   * <p> Set to a negative value to disable it.
+   *
+   * @param webSocketClosingTimeout the timeout is seconds
+   * @return a reference to this, so the API can be used fluently
+   */
+  public HttpServerOptions setWebSocketClosingTimeout(int webSocketClosingTimeout) {
+    this.webSocketClosingTimeout = webSocketClosingTimeout;
+    return this;
+  }
+
   @Override
   public boolean equals(Object o) {
     if (this == o) return true;
diff --git a/src/main/java/io/vertx/core/http/impl/Http1xServerConnection.java b/src/main/java/io/vertx/core/http/impl/Http1xServerConnection.java
--- a/src/main/java/io/vertx/core/http/impl/Http1xServerConnection.java
+++ b/src/main/java/io/vertx/core/http/impl/Http1xServerConnection.java
@@ -278,8 +278,14 @@ ServerWebSocketImpl createWebSocket(HttpServerRequestImpl request) {
     if (handshaker == null) {
       return null;
     }
-    ws = new ServerWebSocketImpl(this, handshaker.version() != WebSocketVersion.V00,
-      request, handshaker, options.getMaxWebsocketFrameSize(), options.getMaxWebsocketMessageSize());
+    ws = new ServerWebSocketImpl(
+      this,
+      handshaker.version() != WebSocketVersion.V00,
+      options.getWebSocketClosingTimeout(),
+      request,
+      handshaker,
+      options.getMaxWebsocketFrameSize(),
+      options.getMaxWebsocketMessageSize());
     if (METRICS_ENABLED && metrics != null) {
       ws.setMetric(metrics.connected(metric(), request.metric(), ws));
     }
diff --git a/src/main/java/io/vertx/core/http/impl/ServerWebSocketImpl.java b/src/main/java/io/vertx/core/http/impl/ServerWebSocketImpl.java
--- a/src/main/java/io/vertx/core/http/impl/ServerWebSocketImpl.java
+++ b/src/main/java/io/vertx/core/http/impl/ServerWebSocketImpl.java
@@ -16,7 +16,6 @@
 import io.netty.channel.ChannelPipeline;
 import io.netty.channel.ChannelPromise;
 import io.netty.handler.codec.http.HttpResponseStatus;
-import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
 import io.netty.handler.codec.http.websocketx.WebSocketServerHandshaker;
 import io.vertx.codegen.annotations.Nullable;
 import io.vertx.core.AsyncResult;
@@ -48,6 +47,7 @@
 public class ServerWebSocketImpl extends WebSocketImplBase<ServerWebSocketImpl> implements ServerWebSocket {
 
   private final Http1xServerConnection conn;
+  private final long closingTimeoutMS;
   private final String uri;
   private final String path;
   private final String query;
@@ -58,12 +58,14 @@ public class ServerWebSocketImpl extends WebSocketImplBase<ServerWebSocketImpl>
 
   ServerWebSocketImpl(Http1xServerConnection conn,
                       boolean supportsContinuation,
+                      long closingTimeout,
                       HttpServerRequestImpl request,
                       WebSocketServerHandshaker handshaker,
                       int maxWebSocketFrameSize,
                       int maxWebSocketMessageSize) {
     super(conn, supportsContinuation, maxWebSocketFrameSize, maxWebSocketMessageSize);
     this.conn = conn;
+    this.closingTimeoutMS = closingTimeout >= 0 ? closingTimeout * 1000L : -1L;
     this.uri = request.uri();
     this.path = request.path();
     this.query = request.query();
@@ -121,10 +123,10 @@ public X509Certificate[] peerCertificateChain() throws SSLPeerUnverifiedExceptio
   }
 
   @Override
-  public void close(short statusCode, @Nullable String reason, Handler<AsyncResult<Void>> handler) {
+  ChannelPromise doClose(short statusCode, String reason, Handler<AsyncResult<Void>> handler) {
     synchronized (conn) {
       if (closed) {
-        return;
+        return null;
       }
       if (status == null) {
         if (handshakePromise == null) {
@@ -134,7 +136,15 @@ public void close(short statusCode, @Nullable String reason, Handler<AsyncResult
         }
       }
     }
-    super.close(statusCode, reason, handler);
+    ChannelPromise fut = super.doClose(statusCode, reason, handler);
+    fut.addListener(f -> {
+      if (closingTimeoutMS == 0L) {
+        closeConnection();
+      } else if (closingTimeoutMS > 0L) {
+        initiateConnectionCloseTimeout(closingTimeoutMS);
+      }
+    });
+    return fut;
   }
 
   @Override
@@ -231,6 +241,6 @@ public void setHandshake(Future<Integer> future, Handler<AsyncResult<Integer>> h
 
   @Override
   protected void doClose() {
-    conn.channelHandlerContext().close();
+    closeConnection();
   }
 }
diff --git a/src/main/java/io/vertx/core/http/impl/WebSocketImpl.java b/src/main/java/io/vertx/core/http/impl/WebSocketImpl.java
--- a/src/main/java/io/vertx/core/http/impl/WebSocketImpl.java
+++ b/src/main/java/io/vertx/core/http/impl/WebSocketImpl.java
@@ -25,7 +25,6 @@
  */
 public class WebSocketImpl extends WebSocketImplBase<WebSocketImpl> implements WebSocket {
 
-  private long timerID = -1L;
   private final long closingTimeoutMS;
 
   public WebSocketImpl(Http1xClientConnection conn,
@@ -40,9 +39,6 @@ public WebSocketImpl(Http1xClientConnection conn,
   @Override
   void handleClosed() {
     synchronized (conn) {
-      if (timerID != -1L) {
-        conn.getContext().owner().cancelTimer(timerID);
-      }
       HttpClientMetrics metrics = ((Http1xClientConnection) conn).metrics();
       if (metrics != null) {
         metrics.disconnected(getMetric());
@@ -54,13 +50,10 @@ void handleClosed() {
   @Override
   protected void doClose() {
     synchronized (conn) {
-      if (closingTimeoutMS > 0L) {
-        timerID = conn.getContext().owner().setTimer(closingTimeoutMS, id -> {
-          synchronized (conn) {
-            timerID = -1L;
-          }
-          conn.channelHandlerContext().close();
-        });
+      if (closingTimeoutMS == 0L) {
+        closeConnection();
+      } else if (closingTimeoutMS > 0L) {
+        initiateConnectionCloseTimeout(closingTimeoutMS);
       }
     }
   }
diff --git a/src/main/java/io/vertx/core/http/impl/WebSocketImplBase.java b/src/main/java/io/vertx/core/http/impl/WebSocketImplBase.java
--- a/src/main/java/io/vertx/core/http/impl/WebSocketImplBase.java
+++ b/src/main/java/io/vertx/core/http/impl/WebSocketImplBase.java
@@ -69,6 +69,7 @@ public abstract class WebSocketImplBase<S extends WebSocketBase> implements WebS
   protected boolean closed;
   private Short closeStatusCode;
   private String closeReason;
+  private long closeTimeoutID = -1L;
   private MultiMap headers;
   private boolean closeFrameSent;
   private Handler<AsyncResult<Void>> closeOpHandler;
@@ -144,10 +145,14 @@ public void close(short statusCode, String reason) {
   }
 
   @Override
-  public void close(short statusCode, @Nullable String reason, Handler<AsyncResult<Void>> handler) {
+  public void close(short statusCode, String reason, Handler<AsyncResult<Void>> handler) {
+    doClose(statusCode, reason, handler);
+  }
+
+  ChannelPromise doClose(short statusCode, String reason, Handler<AsyncResult<Void>> handler) {
     synchronized (conn) {
       if (closed) {
-        return;
+        return null;
       }
       closed = true;
       closeFrameSent = true;
@@ -157,7 +162,9 @@ public void close(short statusCode, @Nullable String reason, Handler<AsyncResult
     // close the WebSocket by sending a close frame with specified payload
     ByteBuf byteBuf = HttpUtils.generateWSCloseFrameByteBuf(statusCode, reason);
     CloseWebSocketFrame frame = new CloseWebSocketFrame(true, 0, byteBuf);
-    conn.writeToChannel(frame);
+    ChannelPromise fut = conn.channelFuture();
+    conn.writeToChannel(frame, fut);
+    return fut;
   }
 
   @Override
@@ -432,6 +439,22 @@ protected void handleCloseFrame(boolean echo, short statusCode, String reason) {
 
   protected abstract void doClose();
 
+  /**
+   * Close the connection.
+   */
+  void closeConnection() {
+    conn.channelHandlerContext().close();
+  }
+
+  void initiateConnectionCloseTimeout(long timeoutMillis) {
+    closeTimeoutID = conn.getContext().owner().setTimer(timeoutMillis, id -> {
+      synchronized (conn) {
+        closeTimeoutID = -1L;
+      }
+      closeConnection();
+    });
+  }
+
   private class FrameAggregator implements Handler<WebSocketFrameInternal> {
     private Handler<String> textMessageHandler;
     private Handler<Buffer> binaryMessageHandler;
@@ -577,6 +600,9 @@ void handleClosed() {
     Handler<AsyncResult<Void>> closeOpHandler;
     Handler<Throwable> exceptionHandler;
     synchronized (conn) {
+      if (closeTimeoutID != -1L) {
+        conn.getContext().owner().cancelTimer(closeTimeoutID);
+      }
       closeHandler = this.closeHandler;
       exceptionHandler = closeStatusCode == null ? this.exceptionHandler : null;
       closeOpHandler = this.closeOpHandler;


Test patch:
diff --git a/src/test/java/io/vertx/core/http/WebSocketTest.java b/src/test/java/io/vertx/core/http/WebSocketTest.java
--- a/src/test/java/io/vertx/core/http/WebSocketTest.java
+++ b/src/test/java/io/vertx/core/http/WebSocketTest.java
@@ -2846,8 +2846,17 @@ public void testClientCloseHandshake() {
   }
 
   @Test
-  public void testClientCloseTimeout() {
-    waitFor(2);
+  public void testClientConnectionCloseTimeout() {
+    testClientConnectionCloseTimeout(1);
+  }
+
+  @Test
+  public void testClientConnectionCloseImmediately() {
+    testClientConnectionCloseTimeout(0);
+  }
+
+  public void testClientConnectionCloseTimeout(int timeout) {
+    waitFor(3);
     List<Object> received = Collections.synchronizedList(new ArrayList<>());
     server = vertx.createHttpServer();
     server.requestHandler(req -> {
@@ -2868,8 +2877,12 @@ public void testClientCloseTimeout() {
       }
     });
     server.listen(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, onSuccess(v1 -> {
-      client = vertx.createHttpClient(new HttpClientOptions().setWebSocketClosingTimeout(1));
+      client = vertx.createHttpClient(new HttpClientOptions().setWebSocketClosingTimeout(timeout));
       client.webSocket(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/chat", onSuccess(ws -> {
+        ws.endHandler(v -> {
+          complete();
+        });
+        ws.exceptionHandler(err -> fail());
         ws.closeHandler(v -> {
           assertEquals(1, received.size());
           assertEquals(received.get(0).getClass(), CloseWebSocketFrame.class);
@@ -2882,6 +2895,44 @@ public void testClientCloseTimeout() {
     await();
   }
 
+  @Test
+  public void testServerCloseTimeout() {
+    testServerConnectionClose(1);
+  }
+
+  @Test
+  public void testServerImmediateClose() {
+    testServerConnectionClose(0);
+  }
+
+  public void testServerConnectionClose(int timeout) {
+    waitFor(3);
+    server = vertx.createHttpServer(new HttpServerOptions().setWebSocketClosingTimeout(timeout))
+      .webSocketHandler(ws -> {
+        long now = System.currentTimeMillis();
+        ws.endHandler(v -> fail());
+        ws.exceptionHandler(ignore -> complete());
+        ws.closeHandler(v -> {
+          long elapsed = System.currentTimeMillis() - now;
+          assertTrue(timeout <= elapsed && elapsed < 5000);
+          complete();
+        });
+        ws.close();
+      }).listen(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, onSuccess(s -> {
+        client = vertx.createHttpClient();
+        HttpClientRequest request = client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/");
+        handshake(request, sock -> {
+          NetSocketInternal soi = (NetSocketInternal) sock;
+          soi.channelHandlerContext().pipeline().addBefore("handler", "encoder", new WebSocket13FrameEncoder(true));
+          soi.channelHandlerContext().pipeline().addBefore("handler", "decoder", new WebSocket13FrameDecoder(false, false, 1000));
+          soi.closeHandler(v -> {
+            complete();
+          });
+        });
+      }));
+    await();
+  }
+
   @Test
   public void testCloseServer() {
     client = vertx.createHttpClient();