diff --git a/api/src/main/java/jakarta/json/bind/JsonbConfig.java b/api/src/main/java/jakarta/json/bind/JsonbConfig.java
index 4ed66427..2c2a6e90 100644
--- a/api/src/main/java/jakarta/json/bind/JsonbConfig.java
+++ b/api/src/main/java/jakarta/json/bind/JsonbConfig.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -21,6 +21,7 @@
import jakarta.json.bind.config.PropertyNamingStrategy;
import jakarta.json.bind.config.PropertyVisibilityStrategy;
+import jakarta.json.bind.customization.TypeCustomization;
import jakarta.json.bind.serializer.JsonbDeserializer;
import jakarta.json.bind.serializer.JsonbSerializer;
@@ -126,6 +127,11 @@ public class JsonbConfig {
*/
public static final String DESERIALIZERS = "jsonb.derializers";
+ /**
+ * Property used to specify runtime type customizations.
+ */
+ public static final String TYPE_CUSTOMIZATIONS = "jsonb.type-customizations";
+
/**
* Property used to specify custom binary data strategy.
*/
@@ -360,6 +366,21 @@ public final JsonbConfig withDeserializers(final JsonbDeserializer... deserializ
return this;
}
+ /**
+ * Property used to specify custom runtime type customizations.
+ *
+ * Configures value of {@link #TYPE_CUSTOMIZATIONS} property.
+ *
+ * Calling withTypeCustomizations more than once will merge the type customizations with previous value.
+ *
+ * @param typeCustomizations Type customizations which affects deserialization and serialization of the customized types.
+ * @return This JsonbConfig instance.
+ */
+ public final JsonbConfig withTypeCustomizations(final TypeCustomization... typeCustomizations) {
+ mergeProperties(TYPE_CUSTOMIZATIONS, typeCustomizations, TypeCustomization.class);
+ return this;
+ }
+
/**
* Property used to specify custom binary data strategy.
*
diff --git a/api/src/main/java/jakarta/json/bind/customization/CreatorCustomization.java b/api/src/main/java/jakarta/json/bind/customization/CreatorCustomization.java
new file mode 100644
index 00000000..68976e0b
--- /dev/null
+++ b/api/src/main/java/jakarta/json/bind/customization/CreatorCustomization.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package jakarta.json.bind.customization;
+
+import java.util.List;
+import java.util.Optional;
+
+import jakarta.json.bind.spi.JsonbProvider;
+
+/**
+ * Decorated creator customization.
+ */
+public interface CreatorCustomization {
+
+ /**
+ * Create new {@link CreatorCustomizationBuilder} instance.
+ *
+ * Builder created via this method targets constructors of the class it is bound to.
+ *
+ * @return new creator customization builder instance
+ */
+ static CreatorCustomizationBuilder builder() {
+ return JsonbProvider.provider().newCreatorCustomizationBuilder();
+ }
+
+ /**
+ * Create new {@link CreatorCustomizationBuilder} instance based on creator method name.
+ *
+ * @return new creator customization builder instance
+ */
+ static CreatorCustomizationBuilder builder(String methodName) {
+ return JsonbProvider.provider().newCreatorCustomizationBuilder(methodName);
+ }
+
+ /**
+ * Return creator method name if has been specified.
+ * If the name is empty, it is handled as if it is null.
+ *
+ * @return specified creator method name, otherwise empty
+ */
+ Optional getFactoryMethodName();
+
+ /**
+ * Return immutable {@link List} of the registered parameters. The order of the parameters needs to be the same as they were added.
+ * If no parameters were added, empty {@link List} is returned.
+ *
+ * @return creator parameters
+ */
+ List getParams();
+
+}
diff --git a/api/src/main/java/jakarta/json/bind/customization/CreatorCustomizationBuilder.java b/api/src/main/java/jakarta/json/bind/customization/CreatorCustomizationBuilder.java
new file mode 100644
index 00000000..0e5678ac
--- /dev/null
+++ b/api/src/main/java/jakarta/json/bind/customization/CreatorCustomizationBuilder.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package jakarta.json.bind.customization;
+
+import java.util.function.Consumer;
+
+/**
+ * Builder of the {@link CreatorCustomization} instance.
+ *
+ * When no creator method name is specified, it is assumed that creator is constructor.
+ */
+public interface CreatorCustomizationBuilder {
+
+ /**
+ * Add {@link ParamCustomization} instance.
+ *
+ * All creator parameters are required to be added in exact order as they are on decorated factory method/constructor.
+ *
+ * @param creatorParam creator parameter
+ * @return updated builder instance
+ */
+ CreatorCustomizationBuilder addParam(ParamCustomization creatorParam);
+
+ /**
+ * Add new {@link ParamCustomization} of the property.
+ *
+ * Shortcut method to the {@link #addParam(ParamCustomization)}. It is not required to create {@link CreatorCustomizationBuilder}
+ * since this method will create {@link ParamCustomization} based on the provided parameter class and json name and by calling
+ * {@link ParamCustomization#create(Class, String)} method. No further customizations will be applied.
+ *
+ * All creator parameters are required to be added in exact order as they are on decorated factory method/constructor.
+ *
+ * @param parameterClass class of the parameter
+ * @param jsonName json name of the parameter
+ * @return updated builder instance
+ */
+ default CreatorCustomizationBuilder addParam(Class> parameterClass, String jsonName) {
+ return addParam(ParamCustomization.create(parameterClass, jsonName));
+ }
+
+ /**
+ * Add new {@link PropertyCustomization} of the property.
+ *
+ * Shortcut method to the {@link #addParam(ParamCustomization)}. It is not required to create {@link CreatorCustomizationBuilder}
+ * since this method will create {@link CreatorCustomizationBuilder} based on the provided parameter class and json name.
+ * Created builder is provided over the paramBuilder.
+ *
+ * All creator parameters are required to be added in exact order as they are on decorated factory method/constructor.
+ *
+ * Example usage:
+ * {@code
+ * creatorBuilder.addParameter(String.class, "jsonName", paramBuilder -> paramBuilder.nillable(true));
+ * }
+ *
+ * @param parameterClass class of the parameter
+ * @param jsonName json name of the parameter
+ * @param paramBuilder builder used to customize parameter
+ * @return updated builder instance
+ */
+ default CreatorCustomizationBuilder addParam(Class> parameterClass,
+ String jsonName,
+ Consumer paramBuilder) {
+ ParamCustomizationBuilder builder = ParamCustomization.builder(parameterClass, jsonName);
+ paramBuilder.accept(builder);
+ return addParam(builder.build());
+ }
+
+ /**
+ * Build the new instance of the {@link CreatorCustomization}.
+ *
+ * @return new {@link CreatorCustomization} instance
+ */
+ CreatorCustomization build();
+
+}
diff --git a/api/src/main/java/jakarta/json/bind/customization/JsonbCustomization.java b/api/src/main/java/jakarta/json/bind/customization/JsonbCustomization.java
new file mode 100644
index 00000000..00ed7bdd
--- /dev/null
+++ b/api/src/main/java/jakarta/json/bind/customization/JsonbCustomization.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package jakarta.json.bind.customization;
+
+import java.util.Optional;
+
+import jakarta.json.bind.adapter.JsonbAdapter;
+import jakarta.json.bind.serializer.JsonbDeserializer;
+
+/**
+ * Common interface for all the customizations.
+ */
+public interface JsonbCustomization {
+
+ /**
+ * Return {@link JsonbDeserializer} of the component.
+ *
+ * @return component deserializer instance, otherwise empty
+ */
+ Optional> getDeserializer();
+
+ /**
+ * Return {@link JsonbAdapter} of the component.
+ *
+ * @return component adapter instance, otherwise empty
+ */
+ Optional> getAdapter();
+
+}
diff --git a/api/src/main/java/jakarta/json/bind/customization/JsonbCustomizationBuilder.java b/api/src/main/java/jakarta/json/bind/customization/JsonbCustomizationBuilder.java
new file mode 100644
index 00000000..d64c03be
--- /dev/null
+++ b/api/src/main/java/jakarta/json/bind/customization/JsonbCustomizationBuilder.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package jakarta.json.bind.customization;
+
+import java.text.DateFormat;
+import java.text.NumberFormat;
+import java.util.Locale;
+
+import jakarta.json.bind.adapter.JsonbAdapter;
+import jakarta.json.bind.serializer.JsonbDeserializer;
+
+/**
+ * Common interface for all customization builders.
+ */
+public interface JsonbCustomizationBuilder, B extends JsonbCustomization> {
+
+ /**
+ * Whether this component can be nillable.
+ *
+ * @param nillable nillable component
+ * @return updated builder instance
+ */
+ T nillable(boolean nillable);
+
+ /**
+ * Ignore nillable customization of this component.
+ *
+ * @return updated builder instance
+ */
+ T ignoreNillable();
+
+ /**
+ * Set {@link JsonbDeserializer} which should be used.
+ *
+ * @param deserializer component deserializer
+ * @return updated builder instance
+ */
+ T deserializer(JsonbDeserializer> deserializer);
+
+ /**
+ * Ignore deserializer of this component.
+ *
+ * @return updated builder instance
+ */
+ T ignoreDeserializer();
+
+ /**
+ * Set {@link JsonbAdapter} which should be used.
+ *
+ * @param adapter component adapter
+ * @return updated builder instance
+ */
+ T adapter(JsonbAdapter, ?> adapter);
+
+ /**
+ * Ignore adapter of this component.
+ *
+ * @return updated builder instance
+ */
+ T ignoreAdapter();
+
+ /**
+ * Set number format and locale which should be used.
+ *
+ * @param numberFormat number format
+ * @param locale locale
+ * @return updated builder instance
+ */
+ T numberFormat(String numberFormat, Locale locale);
+
+ /**
+ * Set number format which should be used.
+ *
+ * @param numberFormat number format
+ * @return updated builder instance
+ */
+ T numberFormat(String numberFormat);
+
+ /**
+ * Set locale which should be used.
+ *
+ * @param locale locale
+ * @return updated builder instance
+ */
+ T numberFormat(Locale locale);
+
+ /**
+ * Set {@link NumberFormat} instance which should be used.
+ *
+ * @param numberFormat pre created NumberFormat instance
+ * @return updated builder instance
+ */
+ T numberFormat(NumberFormat numberFormat);
+
+ /**
+ * Ignore number format customization of this component.
+ *
+ * @return updated builder instance
+ */
+ T ignoreNumberFormat();
+
+ /**
+ * Set date format and locale which should be used.
+ *
+ * @param dateFormat date format
+ * @param locale locale
+ * @return updated builder instance
+ */
+ T dateFormat(String dateFormat, Locale locale);
+
+ /**
+ * Set date format which should be used.
+ *
+ * @param dateFormat date format
+ * @return updated builder instance
+ */
+ T dateFormat(String dateFormat);
+
+ /**
+ * Set locale which should be used.
+ *
+ * @param locale locale
+ * @return updated builder instance
+ */
+ T dateFormat(Locale locale);
+
+ /**
+ * Set {@link DateFormat} instance which should be used.
+ *
+ * @param dateFormat pre created DateFormat instance
+ * @return updated builder instance
+ */
+ T dateFormat(DateFormat dateFormat);
+
+ /**
+ * Ignore date format customization of this component.
+ *
+ * @return updated builder instance
+ */
+ T ignoreDateFormat();
+
+ /**
+ * Ignore all the customizations.
+ *
+ * @return updated builder instance
+ */
+ T ignoreAllCustomizations();
+
+ /**
+ * Build the new instance from this builder.
+ *
+ * @return new instance
+ */
+ B build();
+
+}
diff --git a/api/src/main/java/jakarta/json/bind/customization/ParamCustomization.java b/api/src/main/java/jakarta/json/bind/customization/ParamCustomization.java
new file mode 100644
index 00000000..770ef246
--- /dev/null
+++ b/api/src/main/java/jakarta/json/bind/customization/ParamCustomization.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package jakarta.json.bind.customization;
+
+import java.util.Objects;
+
+import jakarta.json.bind.spi.JsonbProvider;
+
+/**
+ * Decorated parameter customization.
+ */
+public interface ParamCustomization extends JsonbCustomization, ScopelessCustomization {
+
+ /**
+ * Create new {@link ParamCustomizationBuilder} instance base on parameter class and its json name.
+ * Both class and json name are required to be non-null or empty.
+ *
+ * @param paramClass parameter class
+ * @param jsonName parameter json name
+ * @return new parameter customization builder instance
+ */
+ static ParamCustomizationBuilder builder(Class> paramClass, String jsonName) {
+ Objects.requireNonNull(paramClass, "Parameter class cannot be null");
+ if (jsonName == null || jsonName.isBlank()) {
+ throw new IllegalStateException("Json name cannot be null or empty");
+ }
+ return JsonbProvider.provider().newParamCustomizationBuilder(paramClass, jsonName);
+ }
+
+ /**
+ * Create new instance of {@link ParamCustomization} base on parameter class and its json name.
+ * Both parameter class and json name are required to be non-null or empty.
+ *
+ * @param paramClass parameter class
+ * @param jsonName parameter json name
+ * @return new parameter customization instance
+ */
+ static ParamCustomization create(Class> paramClass, String jsonName) {
+ Objects.requireNonNull(paramClass, "Parameter class cannot be null");
+ if (jsonName == null || jsonName.isBlank()) {
+ throw new IllegalStateException("Json name cannot be null or empty");
+ }
+ return builder(paramClass, jsonName).build();
+ }
+
+ /**
+ * Return parameter json name.
+ *
+ * @return parameter json name
+ */
+ String getJsonName();
+
+ /**
+ * Return parameter class.
+ *
+ * @return parameter class
+ */
+ Class> getParameterClass();
+
+}
diff --git a/api/src/main/java/jakarta/json/bind/customization/ParamCustomizationBuilder.java b/api/src/main/java/jakarta/json/bind/customization/ParamCustomizationBuilder.java
new file mode 100644
index 00000000..4b529523
--- /dev/null
+++ b/api/src/main/java/jakarta/json/bind/customization/ParamCustomizationBuilder.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package jakarta.json.bind.customization;
+
+/**
+ * Builder of the {@link ParamCustomization} instance.
+ */
+public interface ParamCustomizationBuilder extends JsonbCustomizationBuilder {
+
+}
diff --git a/api/src/main/java/jakarta/json/bind/customization/PropertyCustomization.java b/api/src/main/java/jakarta/json/bind/customization/PropertyCustomization.java
new file mode 100644
index 00000000..8c493958
--- /dev/null
+++ b/api/src/main/java/jakarta/json/bind/customization/PropertyCustomization.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package jakarta.json.bind.customization;
+
+import java.util.Arrays;
+import java.util.Optional;
+
+import jakarta.json.bind.spi.JsonbProvider;
+
+/**
+ * Decorated property customization.
+ */
+public interface PropertyCustomization extends ScopedCustomization {
+
+ /**
+ * Create new {@link PropertyCustomizationBuilder} instance base on property name.
+ * Property name is required to be non-null or empty.
+ *
+ * @param propertyName name of the decorated property
+ * @return new property customization builder instance
+ */
+ static PropertyCustomizationBuilder builder(String propertyName) {
+ if (propertyName == null || propertyName.isBlank()) {
+ throw new IllegalStateException("Property name cannot be null or empty");
+ }
+ return JsonbProvider.provider().newPropertyCustomizationBuilder(propertyName);
+ }
+
+ /**
+ * Return the original property name.
+ *
+ * @return property name
+ */
+ String getPropertyName();
+
+ /**
+ * Return if the property is transient in the given {@link Scope}.
+ *
+ * @param scope required scope
+ * @return property transient state, otherwise empty
+ */
+ Optional getTransientProperty(Scope scope);
+
+ /**
+ * Return custom property name in the given {@link Scope}.
+ *
+ * @param scope required scope
+ * @return property custom name, otherwise empty
+ */
+ Optional getName(Scope scope);
+
+ default PropertyCustomizationBuilder toBuilder() {
+ PropertyCustomizationBuilder builder = builder(getPropertyName());
+ getAdapter().ifPresent(builder::adapter);
+ getDeserializer().ifPresent(builder::deserializer);
+ getSerializer().ifPresent(builder::serializer);
+ Arrays.stream(Scope.values())
+ .forEach(scope -> {
+ getTransientProperty(scope).ifPresent(value -> builder.transientProperty(value, scope));
+ getDateFormat(scope).ifPresent(value -> builder.dateFormat(value, scope));
+ getName(scope).ifPresent(value -> builder.name(value, scope));
+ getNillable(scope).ifPresent(value -> builder.nillable(value, scope));
+ getNumberFormat(scope).ifPresent(value -> builder.numberFormat(value, scope));
+ });
+ return builder;
+ }
+
+}
diff --git a/api/src/main/java/jakarta/json/bind/customization/PropertyCustomizationBuilder.java b/api/src/main/java/jakarta/json/bind/customization/PropertyCustomizationBuilder.java
new file mode 100644
index 00000000..3e7c6c57
--- /dev/null
+++ b/api/src/main/java/jakarta/json/bind/customization/PropertyCustomizationBuilder.java
@@ -0,0 +1,394 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package jakarta.json.bind.customization;
+
+import java.text.DateFormat;
+import java.text.NumberFormat;
+import java.util.Locale;
+
+import jakarta.json.bind.annotation.JsonbDateFormat;
+
+/**
+ * Builder of the specific class property customization.
+ *
+ * Customization of the property accessor methods is done over the methods with the {@link Scope}
+ * parameter. Methods without any specific {@link Scope} parameter are setting required customization
+ * to the deserialization and serialization.
+ *
+ * For example having getter method with custom name like this
+ *
{@code
+ * @JsonbProperty("customName")
+ * public String getExample() { .... }
+ * }
+ * is effectively the same as having it set like this using the builder
+ * {@code
+ * builder.name("customName", Scope.DESERIALIZATION);
+ * }
+ *
+ */
+public interface PropertyCustomizationBuilder
+ extends SerializationCustomizationBuilder {
+
+ /**
+ * Set custom property name for serialization and deserialization.
+ *
+ * @param name custom property name
+ * @return updated builder instance
+ */
+ default PropertyCustomizationBuilder name(String name) {
+ return name(name, Scope.SERIALIZATION).name(name, Scope.DESERIALIZATION);
+ }
+
+ /**
+ * Set custom property name bound to the selected {@link Scope}.
+ *
+ * @param name custom property name
+ * @param scope scope to which this name is bound
+ * @return updated builder instance
+ */
+ PropertyCustomizationBuilder name(String name, Scope scope);
+
+ /**
+ * Ignore custom property name.
+ *
+ * Custom property name will be ignored for serialization and deserialization.
+ *
+ * @return updated builder instance
+ */
+ default PropertyCustomizationBuilder ignoreName() {
+ return ignoreName(Scope.SERIALIZATION).ignoreName(Scope.DESERIALIZATION);
+ }
+
+ /**
+ * Ignore custom property name in the given {@link Scope}.
+ *
+ * @return updated builder instance
+ */
+ PropertyCustomizationBuilder ignoreName(Scope scope);
+
+ /**
+ * Whether this component can be nillable.
+ *
+ * This number format is used for serialization and deserialization of the property.
+ *
+ * @param nillable nillable component
+ * @return updated builder instance
+ */
+ @Override
+ default PropertyCustomizationBuilder nillable(boolean nillable) {
+ return nillable(nillable, Scope.SERIALIZATION).nillable(nillable, Scope.DESERIALIZATION);
+ }
+
+ /**
+ * Whether this component should be nillable in the given {@link Scope}.
+ *
+ * @param nillable nillable component
+ * @param scope scope of the nillable
+ * @return updated builder instance
+ */
+ PropertyCustomizationBuilder nillable(boolean nillable, Scope scope);
+
+ /**
+ * Ignore nillable customization of this component.
+ *
+ * Nillable customization will be ignored for both serialization and deserialization.
+ *
+ * @return updated builder instance
+ */
+ @Override
+ default PropertyCustomizationBuilder ignoreNillable() {
+ return ignoreNillable(Scope.SERIALIZATION).ignoreNillable(Scope.DESERIALIZATION);
+ }
+
+ /**
+ * Ignore nillable customization of this component in the given {@link Scope}.
+ *
+ * @param scope ignored scope
+ * @return updated builder instance
+ */
+ PropertyCustomizationBuilder ignoreNillable(Scope scope);
+
+ /**
+ * Set number format which should be used.
+ *
+ * This number format is used for serialization and deserialization of the property.
+ *
+ * @param numberFormat number format
+ * @return updated builder instance
+ */
+ @Override
+ default PropertyCustomizationBuilder numberFormat(String numberFormat) {
+ return numberFormat(numberFormat, Scope.SERIALIZATION).numberFormat(numberFormat, Scope.DESERIALIZATION);
+ }
+
+ /**
+ * Set number format locale which should be used.
+ *
+ * This locale is used for serialization and deserialization of the property.
+ *
+ * @param locale locale
+ * @return updated builder instance
+ */
+ @Override
+ default PropertyCustomizationBuilder numberFormat(Locale locale) {
+ return numberFormat(locale, Scope.SERIALIZATION).numberFormat(locale, Scope.DESERIALIZATION);
+ }
+
+ /**
+ * Set number format and locale which should be used.
+ *
+ * Both number format and locale are used for serialization and deserialization of the property.
+ *
+ * @param numberFormat number format
+ * @param locale locale
+ * @return updated builder instance
+ */
+ @Override
+ default PropertyCustomizationBuilder numberFormat(String numberFormat, Locale locale) {
+ return numberFormat(numberFormat, locale, Scope.SERIALIZATION).numberFormat(numberFormat, locale, Scope.DESERIALIZATION);
+ }
+
+ /**
+ * Set {@link NumberFormat} instance which should be used.
+ *
+ * This {@link NumberFormat} instance is used for serialization and deserialization of the property.
+ *
+ * @param numberFormat pre created NumberFormat instance
+ * @return updated builder instance
+ */
+ @Override
+ default PropertyCustomizationBuilder numberFormat(NumberFormat numberFormat) {
+ return numberFormat(numberFormat, Scope.SERIALIZATION).numberFormat(numberFormat, Scope.DESERIALIZATION);
+ }
+
+ /**
+ * Set number format and locale which should be used in the given {@link Scope}.
+ *
+ * @param numberFormat number format
+ * @param locale number format locale
+ * @param scope scope of the format
+ * @return updated builder instance
+ */
+ PropertyCustomizationBuilder numberFormat(String numberFormat, Locale locale, Scope scope);
+
+ /**
+ * Set {@link NumberFormat} instance which should be used in the given {@link Scope}.
+ *
+ * @param numberFormat pre created NumberFormat instance
+ * @param scope scope of the format
+ * @return updated builder instance
+ */
+ PropertyCustomizationBuilder numberFormat(NumberFormat numberFormat, Scope scope);
+
+ /**
+ * Set number format which should be used in the given {@link Scope}.
+ *
+ * @param numberFormat number format
+ * @param scope scope of the format
+ * @return updated builder instance
+ */
+ default PropertyCustomizationBuilder numberFormat(String numberFormat, Scope scope) {
+ return numberFormat(numberFormat, Locale.getDefault(), scope);
+ }
+
+ /**
+ * Set number format locale which should be used in the given {@link Scope}.
+ *
+ * @param locale number format locale
+ * @param scope scope of the format
+ * @return updated builder instance
+ */
+ default PropertyCustomizationBuilder numberFormat(Locale locale, Scope scope) {
+ return numberFormat("", locale, scope);
+ }
+
+ /**
+ * Ignore number format and locale customization of this property.
+ *
+ * Both number format and locale will be ignored for serialization and deserialization of the property.
+ *
+ * @return updated builder instance
+ */
+ @Override
+ default PropertyCustomizationBuilder ignoreNumberFormat() {
+ return ignoreNumberFormat(Scope.SERIALIZATION).ignoreTransient(Scope.DESERIALIZATION);
+ }
+
+ /**
+ * Ignore number format customization of this property in the given {@link Scope}.
+ *
+ * @param scope ignored scope
+ * @return updated builder instance
+ */
+ PropertyCustomizationBuilder ignoreNumberFormat(Scope scope);
+
+ /**
+ * Set date format and locale which should be used.
+ *
+ * Both date format and locale are used for serialization and deserialization of the property.
+ *
+ * @param dateFormat date format
+ * @param locale locale
+ * @return updated builder instance
+ */
+ @Override
+ default PropertyCustomizationBuilder dateFormat(String dateFormat, Locale locale) {
+ return dateFormat(dateFormat, locale, Scope.SERIALIZATION).dateFormat(dateFormat, locale, Scope.DESERIALIZATION);
+ }
+
+ /**
+ * Set date format which should be used.
+ *
+ * This date format is used for serialization and deserialization of the property.
+ *
+ * @param dateFormat date format
+ * @return updated builder instance
+ */
+ @Override
+ default PropertyCustomizationBuilder dateFormat(String dateFormat) {
+ return dateFormat(dateFormat, Locale.getDefault(), Scope.SERIALIZATION)
+ .dateFormat(dateFormat, Locale.getDefault(), Scope.DESERIALIZATION);
+ }
+
+
+ /**
+ * Set date format locale which should be used.
+ *
+ * This date format locale is used for serialization and deserialization of the property.
+ *
+ * @param locale locale
+ * @return updated builder instance
+ */
+ @Override
+ default PropertyCustomizationBuilder dateFormat(Locale locale) {
+ return dateFormat(JsonbDateFormat.DEFAULT_FORMAT, locale, Scope.SERIALIZATION)
+ .dateFormat(JsonbDateFormat.DEFAULT_FORMAT, locale, Scope.DESERIALIZATION);
+ }
+
+ /**
+ * Set {@link DateFormat} instance which should be used.
+ *
+ * This {@link DateFormat} instance is used for serialization and deserialization of the property.
+ *
+ * @param dateFormat pre created DateFormat instance
+ * @return updated builder instance
+ */
+ @Override
+ default PropertyCustomizationBuilder dateFormat(DateFormat dateFormat) {
+ return dateFormat(dateFormat, Scope.SERIALIZATION).dateFormat(dateFormat, Scope.DESERIALIZATION);
+ }
+
+ /**
+ * Set date format and locale which should be used in the given {@link Scope}.
+ *
+ * @param dateFormat date format
+ * @param locale date format locale
+ * @param scope scope of the format
+ * @return updated builder instance
+ */
+ PropertyCustomizationBuilder dateFormat(String dateFormat, Locale locale, Scope scope);
+
+ /**
+ * Set {@link DateFormat} instance which should be used in the given {@link Scope}.
+ *
+ * @param dateFormat pre created DateFormat instance
+ * @return updated builder instance
+ */
+ PropertyCustomizationBuilder dateFormat(DateFormat dateFormat, Scope scope);
+
+ /**
+ * Set date format which should be used in the given {@link Scope}.
+ *
+ * @param dateFormat date format
+ * @param scope scope of the format
+ * @return updated builder instance
+ */
+ default PropertyCustomizationBuilder dateFormat(String dateFormat, Scope scope) {
+ return dateFormat(dateFormat, Locale.getDefault(), scope);
+ }
+
+ /**
+ * Set date format locale which should be used in the given {@link Scope}.
+ *
+ * @param locale date format locale
+ * @param scope scope of the format
+ * @return updated builder instance
+ */
+ default PropertyCustomizationBuilder dateFormat(Locale locale, Scope scope) {
+ return dateFormat(JsonbDateFormat.DEFAULT_FORMAT, locale, scope);
+ }
+
+ /**
+ * Ignore date format customization of this property.
+ *
+ * The date format is ignored for serialization and deserialization of the property.
+ *
+ * @return updated builder instance
+ */
+ @Override
+ default PropertyCustomizationBuilder ignoreDateFormat() {
+ return ignoreDateFormat(Scope.SERIALIZATION).ignoreDateFormat(Scope.DESERIALIZATION);
+ }
+
+ /**
+ * Ignore date format customization of this property in the given {@link Scope}.
+ *
+ * @return updated builder instance
+ */
+ PropertyCustomizationBuilder ignoreDateFormat(Scope scope);
+
+ /**
+ * Whether the property is transient.
+ *
+ * This value of the property will be set for serialization and deserialization.
+ *
+ * @param isTransient transient property
+ * @return updated builder instance
+ */
+ default PropertyCustomizationBuilder transientProperty(boolean isTransient) {
+ return transientProperty(isTransient, Scope.SERIALIZATION).transientProperty(isTransient, Scope.DESERIALIZATION);
+ }
+
+ /**
+ * Whether the property is transient in the given {@link Scope}.
+ *
+ * @param isTransient transient property
+ * @param scope transient scope
+ * @return updated builder instance
+ */
+ PropertyCustomizationBuilder transientProperty(boolean isTransient, Scope scope);
+
+ /**
+ * Ignore transient status of this property.
+ *
+ * Transient will be ignored for serialization and deserialization.
+ *
+ * @return updated builder instance
+ */
+ default PropertyCustomizationBuilder ignoreTransient() {
+ return ignoreTransient(Scope.SERIALIZATION).ignoreTransient(Scope.DESERIALIZATION);
+ }
+
+ /**
+ * Ignore transient status of this property in the given {@link Scope}.
+ *
+ * @param scope transient ignore scope
+ * @return updated builder instance
+ */
+ PropertyCustomizationBuilder ignoreTransient(Scope scope);
+
+}
diff --git a/api/src/main/java/jakarta/json/bind/customization/Scope.java b/api/src/main/java/jakarta/json/bind/customization/Scope.java
new file mode 100644
index 00000000..2247d8a5
--- /dev/null
+++ b/api/src/main/java/jakarta/json/bind/customization/Scope.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package jakarta.json.bind.customization;
+
+/**
+ * Scope of upon which the customization should be used.
+ */
+public enum Scope {
+
+ /**
+ * Transformation from Java object to the JSON.
+ */
+ SERIALIZATION,
+
+ /**
+ * Transformation from JSON to the Java object.
+ */
+ DESERIALIZATION,
+
+}
diff --git a/api/src/main/java/jakarta/json/bind/customization/ScopedCustomization.java b/api/src/main/java/jakarta/json/bind/customization/ScopedCustomization.java
new file mode 100644
index 00000000..684e4bde
--- /dev/null
+++ b/api/src/main/java/jakarta/json/bind/customization/ScopedCustomization.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package jakarta.json.bind.customization;
+
+import java.text.DateFormat;
+import java.text.NumberFormat;
+import java.util.Optional;
+
+/**
+ * Customization methods with the scope.
+ */
+public interface ScopedCustomization extends SerializationCustomization {
+
+ /**
+ * Return {@link NumberFormat} specified to the required {@link Scope}.
+ *
+ * @param scope required scope
+ * @return specified {@link NumberFormat} instance, otherwise empty
+ */
+ Optional getNumberFormat(Scope scope);
+
+ /**
+ * Return {@link DateFormat} specified to the required {@link Scope}.
+ *
+ * @param scope required scope
+ * @return specified {@link DateFormat} instance, otherwise empty
+ */
+ Optional getDateFormat(Scope scope);
+
+ /**
+ * Return whether the component can be nillable in the given {@link Scope}.
+ * If no explicit value has been set, empty optional is returned.
+ *
+ * @param scope required scope
+ * @return property nillable state, if not explicitly set empty is returned
+ */
+ Optional getNillable(Scope scope);
+
+}
diff --git a/api/src/main/java/jakarta/json/bind/customization/ScopelessCustomization.java b/api/src/main/java/jakarta/json/bind/customization/ScopelessCustomization.java
new file mode 100644
index 00000000..82dac7dc
--- /dev/null
+++ b/api/src/main/java/jakarta/json/bind/customization/ScopelessCustomization.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package jakarta.json.bind.customization;
+
+import java.text.DateFormat;
+import java.text.NumberFormat;
+import java.util.Optional;
+
+/**
+ * Customization methods without the scope.
+ */
+public interface ScopelessCustomization extends JsonbCustomization {
+
+ /**
+ * Return specified {@link NumberFormat}.
+ *
+ * @return specified {@link NumberFormat} instance, otherwise empty
+ */
+ Optional getNumberFormat();
+
+ /**
+ * Return {@link DateFormat}.
+ *
+ * @return specified {@link DateFormat} instance, otherwise empty
+ */
+ Optional getDateFormat();
+
+ /**
+ * Return whether this component can be nillable.
+ * If no explicit value has been set, empty optional is returned.
+ *
+ * @return property nillable state, if not explicitly set empty is returned
+ */
+ Optional getNillable();
+
+
+}
diff --git a/api/src/main/java/jakarta/json/bind/customization/SerializationCustomization.java b/api/src/main/java/jakarta/json/bind/customization/SerializationCustomization.java
new file mode 100644
index 00000000..1b151770
--- /dev/null
+++ b/api/src/main/java/jakarta/json/bind/customization/SerializationCustomization.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package jakarta.json.bind.customization;
+
+import java.util.Optional;
+
+import jakarta.json.bind.serializer.JsonbSerializer;
+
+/**
+ * Extension of the {@link JsonbCustomization} over the serialization specific methods.
+ */
+public interface SerializationCustomization extends JsonbCustomization {
+
+ /**
+ * Return {@link JsonbSerializer} of the component.
+ *
+ * @return component serializer instance, otherwise empty
+ */
+ Optional> getSerializer();
+
+}
diff --git a/api/src/main/java/jakarta/json/bind/customization/SerializationCustomizationBuilder.java b/api/src/main/java/jakarta/json/bind/customization/SerializationCustomizationBuilder.java
new file mode 100644
index 00000000..c840e87d
--- /dev/null
+++ b/api/src/main/java/jakarta/json/bind/customization/SerializationCustomizationBuilder.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package jakarta.json.bind.customization;
+
+import jakarta.json.bind.serializer.JsonbSerializer;
+
+/**
+ * Extension of the {@link JsonbCustomizationBuilder} over the serialization specific methods.
+ */
+public interface SerializationCustomizationBuilder, B extends JsonbCustomization>
+ extends JsonbCustomizationBuilder {
+
+ /**
+ * Set {@link JsonbSerializer} which should be used for this component.
+ *
+ * @param serializer component deserializer
+ * @return updated builder instance
+ */
+ T serializer(JsonbSerializer> serializer);
+
+ /**
+ * Ignore serializer of this component.
+ *
+ * @return updated builder instance
+ */
+ T ignoreSerializer();
+
+}
diff --git a/api/src/main/java/jakarta/json/bind/customization/TypeCustomization.java b/api/src/main/java/jakarta/json/bind/customization/TypeCustomization.java
new file mode 100644
index 00000000..e12fbbbe
--- /dev/null
+++ b/api/src/main/java/jakarta/json/bind/customization/TypeCustomization.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package jakarta.json.bind.customization;
+
+import java.util.Map;
+import java.util.Optional;
+
+import jakarta.json.bind.config.PropertyOrderStrategy;
+import jakarta.json.bind.config.PropertyVisibilityStrategy;
+import jakarta.json.bind.spi.JsonbProvider;
+
+/**
+ * Type customization.
+ */
+public interface TypeCustomization extends SerializationCustomization, ScopelessCustomization {
+
+ /**
+ * Create new {@link TypeCustomizationBuilder} instance base on type class.
+ * Parameter typeClass is required to be non-null.
+ *
+ * @param typeClass type class
+ * @return new type customization builder instance
+ */
+ static TypeCustomizationBuilder builder(Class> typeClass) {
+ return JsonbProvider.provider().newTypeCustomizationBuilder(typeClass);
+ }
+
+ /**
+ * Return type which is this customization bound to.
+ *
+ * @return type which is this customization bound to
+ */
+ Class> getType();
+
+ /**
+ * Return {@link PropertyOrderStrategy} of the decorated type.
+ *
+ * @return property order strategy instance, otherwise empty
+ */
+ Optional getPropertyOrderStrategy();
+
+ /**
+ * Return {@link PropertyVisibilityStrategy} of the decorated type.
+ *
+ * @return property visibility strategy instance, otherwise empty
+ */
+ Optional getPropertyVisibilityStrategy();
+
+ /**
+ * Return registered property customizations.
+ * If no property is registered, empty {@link Map} is returned.
+ *
+ * @return map of the registered property customizations, otherwise empty map
+ */
+ Map getProperties();
+
+ /**
+ * Return {@link CreatorCustomization} of the decorated type.
+ *
+ * @return creator customization instance, otherwise empty
+ */
+ Optional getCreator();
+
+ /**
+ * Convert {@link TypeCustomization} to the {@link TypeCustomizationBuilder} with prefilled values from original object.
+ *
+ * @return new {@link TypeCustomizationBuilder} instance
+ */
+ default TypeCustomizationBuilder toBuilder() {
+ TypeCustomizationBuilder builder = builder(getType());
+ getNillable().ifPresent(builder::nillable);
+ getDeserializer().ifPresent(builder::deserializer);
+ getSerializer().ifPresent(builder::serializer);
+ getAdapter().ifPresent(builder::adapter);
+ getNumberFormat().ifPresent(builder::numberFormat);
+ getDateFormat().ifPresent(builder::dateFormat);
+ getCreator().ifPresent(builder::creator);
+ getPropertyOrderStrategy().ifPresent(builder::propertyOrderStrategy);
+ getPropertyVisibilityStrategy().ifPresent(builder::visibilityStrategy);
+ getProperties().values().forEach(builder::property);
+ return builder;
+ }
+
+}
diff --git a/api/src/main/java/jakarta/json/bind/customization/TypeCustomizationBuilder.java b/api/src/main/java/jakarta/json/bind/customization/TypeCustomizationBuilder.java
new file mode 100644
index 00000000..26215161
--- /dev/null
+++ b/api/src/main/java/jakarta/json/bind/customization/TypeCustomizationBuilder.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package jakarta.json.bind.customization;
+
+import java.util.Objects;
+import java.util.function.Consumer;
+
+import jakarta.json.bind.config.PropertyOrderStrategy;
+import jakarta.json.bind.config.PropertyVisibilityStrategy;
+
+/**
+ * Builder of the specific type customization.
+ */
+public interface TypeCustomizationBuilder extends SerializationCustomizationBuilder {
+
+ /**
+ * Set {@link PropertyOrderStrategy} which should be used.
+ *
+ * @param strategy property order strategy
+ * @return updated builder instance
+ */
+ TypeCustomizationBuilder propertyOrderStrategy(PropertyOrderStrategy strategy);
+
+ /**
+ * Ignore property order strategy.
+ *
+ * @return updated builder instance
+ */
+ TypeCustomizationBuilder ignorePropertyOrderStrategy();
+
+ /**
+ * Set {@link PropertyVisibilityStrategy} which should be used.
+ *
+ * @param strategy property visibility strategy
+ * @return updated builder instance
+ */
+ TypeCustomizationBuilder visibilityStrategy(PropertyVisibilityStrategy strategy);
+
+ /**
+ * Ignore visibility strategy.
+ *
+ * @return updated builder instance
+ */
+ TypeCustomizationBuilder ignoreVisibilityStrategy();
+
+ /**
+ * Add new {@link PropertyCustomization} of the property.
+ *
+ * @param propertyCustomization property customization
+ * @return updated builder instance
+ */
+ TypeCustomizationBuilder property(PropertyCustomization propertyCustomization);
+
+ /**
+ * Add new {@link PropertyCustomization} of the property.
+ *
+ * Shortcut method to the {@link #property(PropertyCustomization)}. It is not required to create {@link PropertyCustomizationBuilder}
+ * since this method will create it based on the provided property name and expose it over the propertyBuilder parameter.
+ *
+ * Example usage:
+ * {@code
+ * typeBuilder.property("exampleProperty", propertyBuilder -> propertyBuilder.nillable(true));
+ * }
+ * @param propertyName name of the class property
+ * @param propertyBuilder builder used to customize property
+ * @return updated builder instance
+ */
+ default TypeCustomizationBuilder property(String propertyName, Consumer propertyBuilder) {
+ PropertyCustomizationBuilder builder = PropertyCustomization.builder(Objects.requireNonNull(propertyName));
+ propertyBuilder.accept(builder);
+ return property(builder.build());
+ }
+
+ /**
+ * Add new {@link CreatorCustomization} of the type.
+ *
+ * @param creatorCustomization creator customization
+ * @return updated builder instance
+ */
+ TypeCustomizationBuilder creator(CreatorCustomization creatorCustomization);
+
+ /**
+ * Add new {@link CreatorCustomization} of the type.
+ *
+ * Shortcut method to the {@link #creator(CreatorCustomization)}. It is not required to create {@link CreatorCustomizationBuilder}
+ * since this method will create it based on the creator method name and expose it over the creatorBuilder parameter.
+ *
+ * Example usage:
+ * {@code
+ * typeBuilder.creator("factoryMethodName",
+ * creatorBuilder -> creatorBuilder.addParameter(String.class, "firstParameter"));
+ * }
+ * @param creatorMethodName creator method name
+ * @param creatorBuilder creator builder instance consumer
+ * @return updated builder instance
+ */
+ default TypeCustomizationBuilder creator(String creatorMethodName, Consumer creatorBuilder) {
+ CreatorCustomizationBuilder builder = CreatorCustomization.builder(creatorMethodName);
+ creatorBuilder.accept(builder);
+ return creator(builder.build());
+ }
+
+ /**
+ * Add new {@link CreatorCustomization} of the type.
+ *
+ * Shortcut method to the {@link #creator(CreatorCustomization)}. It is not required to create {@link CreatorCustomizationBuilder}
+ * since this method will create it and expose it over the creatorBuilder parameter. Since no factory method name is
+ * provided, this creator builder is targeting constructors.
+ *
+ * Example usage:
+ * {@code
+ * typeBuilder.creator(creatorBuilder -> creatorBuilder.addParameter(String.class, "firstParameter"));
+ * }
+ * @param creatorBuilder creator builder instance consumer
+ * @return updated builder instance
+ */
+ default TypeCustomizationBuilder creator(Consumer creatorBuilder) {
+ CreatorCustomizationBuilder builder = CreatorCustomization.builder();
+ creatorBuilder.accept(builder);
+ return creator(builder.build());
+ }
+
+}
diff --git a/api/src/main/java/jakarta/json/bind/customization/package-info.java b/api/src/main/java/jakarta/json/bind/customization/package-info.java
new file mode 100644
index 00000000..c046db25
--- /dev/null
+++ b/api/src/main/java/jakarta/json/bind/customization/package-info.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+/**
+ *
+ * Defines customizations for different components to provide runtime customization with the same capability as
+ * annotation approach.
+ *
+ *
+ * @since JSON Binding 2.1
+ */
+package jakarta.json.bind.customization;
diff --git a/api/src/main/java/jakarta/json/bind/spi/JsonbProvider.java b/api/src/main/java/jakarta/json/bind/spi/JsonbProvider.java
index 250a478c..56ffe34f 100644
--- a/api/src/main/java/jakarta/json/bind/spi/JsonbProvider.java
+++ b/api/src/main/java/jakarta/json/bind/spi/JsonbProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -18,8 +18,13 @@
import jakarta.json.bind.JsonbBuilder;
import jakarta.json.bind.JsonbException;
+import jakarta.json.bind.customization.CreatorCustomizationBuilder;
+import jakarta.json.bind.customization.ParamCustomizationBuilder;
+import jakarta.json.bind.customization.PropertyCustomizationBuilder;
+import jakarta.json.bind.customization.TypeCustomizationBuilder;
import java.util.Iterator;
+import java.util.Objects;
import java.util.ServiceLoader;
/**
@@ -61,6 +66,7 @@ public abstract class JsonbProvider {
*/
private static final String DEFAULT_PROVIDER = "org.eclipse.yasson.JsonBindingProvider";
+ private static volatile JsonbProvider instance = null;
/**
* Protected constructor.
*/
@@ -84,21 +90,28 @@ protected JsonbProvider() {
*/
@SuppressWarnings("UseSpecificCatch")
public static JsonbProvider provider() {
- ServiceLoader loader = ServiceLoader.load(JsonbProvider.class);
- Iterator it = loader.iterator();
- if (it.hasNext()) {
- return it.next();
- }
-
- try {
- Class> clazz = Class.forName(DEFAULT_PROVIDER);
- return (JsonbProvider) clazz.newInstance();
- } catch (ClassNotFoundException x) {
- throw new JsonbException("JSON Binding provider " + DEFAULT_PROVIDER + " not found", x);
- } catch (Exception x) {
- throw new JsonbException("JSON Binding provider " + DEFAULT_PROVIDER
- + " could not be instantiated: " + x, x);
+ if (instance == null) {
+ synchronized (JsonbProvider.class) {
+ if (instance == null) {
+ ServiceLoader loader = ServiceLoader.load(JsonbProvider.class);
+ Iterator it = loader.iterator();
+ if (it.hasNext()) {
+ instance = it.next();
+ } else {
+ try {
+ Class> clazz = Class.forName(DEFAULT_PROVIDER);
+ instance = (JsonbProvider) clazz.newInstance();
+ } catch (ClassNotFoundException x) {
+ throw new JsonbException("JSON Binding provider " + DEFAULT_PROVIDER + " not found", x);
+ } catch (Exception x) {
+ throw new JsonbException("JSON Binding provider " + DEFAULT_PROVIDER
+ + " could not be instantiated: " + x, x);
+ }
+ }
+ }
+ }
}
+ return instance;
}
/**
@@ -123,13 +136,12 @@ public static JsonbProvider provider() {
*/
@SuppressWarnings("UseSpecificCatch")
public static JsonbProvider provider(final String providerName) {
- if (providerName == null) {
- throw new IllegalArgumentException();
+ Objects.requireNonNull(providerName, "providerName is required");
+ if (instance != null && providerName.equals(instance.getClass().getName())) {
+ return instance;
}
ServiceLoader loader = ServiceLoader.load(JsonbProvider.class);
- Iterator it = loader.iterator();
- while (it.hasNext()) {
- JsonbProvider provider = it.next();
+ for (JsonbProvider provider : loader) {
if (providerName.equals(provider.getClass().getName())) {
return provider;
}
@@ -157,4 +169,44 @@ public static JsonbProvider provider(final String providerName) {
*/
public abstract JsonbBuilder create();
+ /**
+ * Return new {@link TypeCustomizationBuilder} instance based on customized type class.
+ *
+ * @param decoratedType customized type class
+ * @return new builder instance
+ */
+ public abstract TypeCustomizationBuilder newTypeCustomizationBuilder(Class> decoratedType);
+
+ /**
+ * Return new {@link PropertyCustomizationBuilder} instance based on customized property name.
+ *
+ * @param propertyName customized property name
+ * @return new builder instance
+ */
+ public abstract PropertyCustomizationBuilder newPropertyCustomizationBuilder(String propertyName);
+
+ /**
+ * Return new {@link CreatorCustomizationBuilder}.
+ *
+ * @return new builder instance
+ */
+ public abstract CreatorCustomizationBuilder newCreatorCustomizationBuilder();
+
+ /**
+ * Return new {@link CreatorCustomizationBuilder} instance based on creator method name.
+ *
+ * @param methodName customized creator method name
+ * @return new builder instance
+ */
+ public abstract CreatorCustomizationBuilder newCreatorCustomizationBuilder(String methodName);
+
+ /**
+ * Return new {@link ParamCustomizationBuilder} instance based on parameter class and its name in JSON document.
+ *
+ * @param paramClass customized parameter class
+ * @param jsonName customized parameter json name
+ * @return new builder instance
+ */
+ public abstract ParamCustomizationBuilder newParamCustomizationBuilder(Class> paramClass, String jsonName);
+
}
diff --git a/api/src/main/java/module-info.java b/api/src/main/java/module-info.java
index 521faf9a..5edeb677 100644
--- a/api/src/main/java/module-info.java
+++ b/api/src/main/java/module-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -19,6 +19,7 @@
exports jakarta.json.bind.adapter;
exports jakarta.json.bind.annotation;
exports jakarta.json.bind.config;
+ exports jakarta.json.bind.customization;
exports jakarta.json.bind.serializer;
exports jakarta.json.bind.spi;