Skip to content

3rd party class customization #279

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
23 changes: 22 additions & 1 deletion api/src/main/java/jakarta/json/bind/JsonbConfig.java
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -21,6 +21,7 @@
import jakarta.json.bind.config.PropertyNamingStrategy;
import jakarta.json.bind.config.PropertyVisibilityStrategy;

import jakarta.json.bind.decorator.TypeDecorator;
import jakarta.json.bind.serializer.JsonbDeserializer;
import jakarta.json.bind.serializer.JsonbSerializer;

Expand Down Expand Up @@ -126,6 +127,11 @@ public class JsonbConfig {
*/
public static final String DESERIALIZERS = "jsonb.derializers";

/**
* Property used to specify custom deserializers.
*/

Choose a reason for hiding this comment

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

if we drop the two entry points from this class we can make this whole PR an appendix - same as proposing the introspector/annotation based solution - of the spec while there is not agreement on the final outcome.
Can enable to have API proposals and decide later (bean validation went that way in its time - for method validation).
Overall blocking point is to have something unified versus something duplicated for 3rd party libraries and I don't see us choosing before next release since both parties seems to either priviledge the interoperability and simplicity or the application API first (being said the introspector API enables to join the API point later if needed whereas decorator does not and keeps two concurrent models in the spec forever).

Wdyt? (trying to not block but not pollute the API too early without enabling 3rd party cases)

Copy link
Contributor

Choose a reason for hiding this comment

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

What exactly do you mean by "drop the two entry points from this class". I am sorry, but I don't understand what you are trying to say. Please explain.

Choose a reason for hiding this comment

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

Not make it explicit in the API (ie use yasson.decorators property without a constant nor a wither.

public static final String TYPE_DECORATORS = "jsonb.type-decorators";

/**
* Property used to specify custom binary data strategy.
*/
Expand Down Expand Up @@ -360,6 +366,21 @@ public final JsonbConfig withDeserializers(final JsonbDeserializer... deserializ
return this;
}

/**
* Property used to specify custom type decorators.
*
* Configures value of {@link #TYPE_DECORATORS} property.
*
* Calling withTypeDecorators more than once will merge the type decorators with previous value.
*
* @param typeDecorators Custom type decorators which affects deserialization and serialization of the decorated types.
* @return This JsonbConfig instance.
*/
public final JsonbConfig withTypeDecorators(final TypeDecorator... typeDecorators) {
mergeProperties(TYPE_DECORATORS, typeDecorators, TypeDecorator.class);
return this;
}

/**
* Property used to specify custom binary data strategy.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -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.decorator;

import java.util.List;
import java.util.Optional;

import jakarta.json.bind.spi.JsonbProvider;

/**
* Decorated creator customization.
*/
public interface CreatorDecorator {

/**
* Create new {@link CreatorDecoratorBuilder} instance.
*
* Builder created via this method targets constructors of the class it is bound to.
*
* @return new creator decorator builder instance
*/
static CreatorDecoratorBuilder builder() {
return JsonbProvider.provider().newCreatorDecoratorBuilder();
}

/**
* Create new {@link CreatorDecoratorBuilder} instance based on creator method name.
*
* @return new creator decorator builder instance
*/
static CreatorDecoratorBuilder builder(String methodName) {
return JsonbProvider.provider().newCreatorDecoratorBuilder(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<String> factoryMethodName();

/**
* Return {@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<ParamDecorator> params();

}
Original file line number Diff line number Diff line change
@@ -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.decorator;

import java.util.function.Consumer;

/**
* Builder of the {@link CreatorDecorator} instance.
*
* When no creator method name is specified, it is assumed that creator is constructor.
*/
public interface CreatorDecoratorBuilder {

/**
* Add {@link ParamDecorator} 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
*/
CreatorDecoratorBuilder addParameter(ParamDecorator creatorParam);

/**
* Add new {@link ParamDecorator} of the property.
* <br>
* Shortcut method to the {@link #addParameter(ParamDecorator)}. It is not required to create {@link CreatorDecoratorBuilder}
* since this method will create {@link ParamDecorator} based on the provided parameter class and json name and by calling
* {@link ParamDecorator#create(Class, String)} method. No further customizations will be applied.
* <br>
* 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 CreatorDecoratorBuilder addParameter(Class<?> parameterClass, String jsonName) {
return addParameter(ParamDecorator.create(parameterClass, jsonName));
}

/**
* Add new {@link PropertyDecorator} of the property.
* <br>
* Shortcut method to the {@link #addParameter(ParamDecorator)}. It is not required to create {@link CreatorDecoratorBuilder}
* since this method will create is based on the provided parameter class and json name. Created builder is provided over
* the paramBuilder.
* <br>
* All creator parameters are required to be added in exact order as they are on decorated factory method/constructor.
* <br>
* Example usage:
* <pre>{@code
* creatorBuilder.addParameter(String.class, "jsonName", paramBuilder -> paramBuilder.nillable(true));
* }</pre>
*
* @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 CreatorDecoratorBuilder addParameter(Class<?> parameterClass,
String jsonName,
Consumer<ParamDecoratorBuilder> paramBuilder) {
ParamDecoratorBuilder builder = ParamDecorator.builder(parameterClass, jsonName);
paramBuilder.accept(builder);
return addParameter(builder.build());
}

/**
* Build the new instance of the {@link CreatorDecorator}.
*
* @return new {@link CreatorDecorator} instance
*/
CreatorDecorator build();

}
69 changes: 69 additions & 0 deletions api/src/main/java/jakarta/json/bind/decorator/JsonbDecorator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* 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.decorator;

import java.text.DateFormat;
import java.text.NumberFormat;
import java.util.Optional;

import jakarta.json.bind.adapter.JsonbAdapter;
import jakarta.json.bind.serializer.JsonbDeserializer;

/**
* Common interface for all of the decorators.
*/
public interface JsonbDecorator {

/**
* Return {@link NumberFormat} specified to the required {@link Scope}.
*
* @param scope required scope
* @return specified {@link NumberFormat} instance, otherwise empty
*/
Optional<NumberFormat> numberFormat(Scope scope);

/**
* Return {@link DateFormat} specified to the required {@link Scope}.
*
* @param scope required scope
* @return specified {@link DateFormat} instance, otherwise empty
*/
Optional<DateFormat> dateFormat(Scope scope);

/**
* Return {@link JsonbDeserializer} of the component.
*
* @return component deserializer instance, otherwise empty
*/
Optional<JsonbDeserializer<?>> deserializer();

/**
* Return {@link JsonbAdapter} of the component.
*
* @return component adapter instance, otherwise empty
*/
Optional<JsonbAdapter<?, ?>> adapter();

/**
* Return if the component can be nillable in the given {@link Scope}.
*
* @param scope required scope
* @return property nillable state, otherwise empty
*/
Optional<Boolean> nillable(Scope scope);

}
Loading