Skip to content

Commit 2d49850

Browse files
authored
Record processing fixed (#530)
Record processing fixed Signed-off-by: David Kral <[email protected]>
1 parent 6eaa09a commit 2d49850

File tree

12 files changed

+211
-31
lines changed

12 files changed

+211
-31
lines changed

src/main/java/org/eclipse/yasson/internal/AnnotationIntrospector.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016, 2021 Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2016, 2022 Oracle and/or its affiliates. All rights reserved.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License v. 2.0 which is available at
@@ -148,12 +148,10 @@ private String getJsonbPropertyCustomizedName(Property property, JsonbAnnotatedE
148148
* @return JsonbCreator metadata object
149149
*/
150150
public JsonbCreator getCreator(Class<?> clazz) {
151-
JsonbCreator jsonbCreator;
151+
JsonbCreator jsonbCreator = null;
152152
Constructor<?>[] declaredConstructors =
153153
AccessController.doPrivileged((PrivilegedAction<Constructor<?>[]>) clazz::getDeclaredConstructors);
154154

155-
jsonbCreator = ClassMultiReleaseExtension.findJsonbCreator(clazz, declaredConstructors, this);
156-
157155
for (Constructor<?> constructor : declaredConstructors) {
158156
final jakarta.json.bind.annotation.JsonbCreator annot = findAnnotation(constructor.getDeclaredAnnotations(),
159157
jakarta.json.bind.annotation.JsonbCreator.class);
@@ -177,7 +175,10 @@ public JsonbCreator getCreator(Class<?> clazz) {
177175
}
178176
}
179177
if (jsonbCreator == null) {
180-
jsonbCreator = constructorPropertiesIntrospector.getCreator(declaredConstructors);
178+
jsonbCreator = ClassMultiReleaseExtension.findCreator(clazz, declaredConstructors, this);
179+
if (jsonbCreator == null) {
180+
jsonbCreator = constructorPropertiesIntrospector.getCreator(declaredConstructors);
181+
}
181182
}
182183
return jsonbCreator;
183184
}

src/main/java/org/eclipse/yasson/internal/ClassMultiReleaseExtension.java

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2021, 2022 Oracle and/or its affiliates. All rights reserved.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License v. 2.0 which is available at
@@ -14,14 +14,19 @@
1414

1515
import java.lang.reflect.Constructor;
1616
import java.lang.reflect.Method;
17+
import java.util.Map;
18+
import java.util.Optional;
19+
20+
import jakarta.json.bind.JsonbException;
1721

1822
import org.eclipse.yasson.internal.model.JsonbCreator;
23+
import org.eclipse.yasson.internal.model.Property;
1924

2025
/**
2126
* Search for instance creator from other sources.
2227
* Mainly intended to add extensibility for different java versions and new features.
2328
*/
24-
class ClassMultiReleaseExtension {
29+
public class ClassMultiReleaseExtension {
2530

2631
private ClassMultiReleaseExtension() {
2732
throw new IllegalStateException("This class cannot be instantiated");
@@ -31,12 +36,18 @@ static boolean shouldTransformToPropertyName(Method method) {
3136
return true;
3237
}
3338

34-
static boolean isGetAccessorMethod(Method method) {
39+
static boolean isSpecialAccessorMethod(Method method, Map<String, Property> classProperties) {
3540
return false;
3641
}
3742

38-
static JsonbCreator findJsonbCreator(Class<?> clazz, Constructor<?>[] declaredConstructors, AnnotationIntrospector introspector) {
43+
static JsonbCreator findCreator(Class<?> clazz,
44+
Constructor<?>[] declaredConstructors,
45+
AnnotationIntrospector introspector) {
3946
return null;
4047
}
4148

49+
public static Optional<JsonbException> exceptionToThrow(Class<?> clazz) {
50+
return Optional.empty();
51+
}
52+
4253
}

src/main/java/org/eclipse/yasson/internal/ClassParser.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2021 Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2022 Oracle and/or its affiliates. All rights reserved.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License v. 2.0 which is available at
@@ -198,7 +198,9 @@ private void parseMethods(Class<?> clazz,
198198
for (Method method : declaredMethods) {
199199
String name = method.getName();
200200
//isBridge method filters out methods inherited from interfaces
201-
if (!isPropertyMethod(method) || method.isBridge() || isSpecialCaseMethod(clazz, method)) {
201+
boolean isAccessorMethod = ClassMultiReleaseExtension.isSpecialAccessorMethod(method, classProperties)
202+
|| isPropertyMethod(method);
203+
if (!isAccessorMethod || method.isBridge() || isSpecialCaseMethod(clazz, method)) {
202204
continue;
203205
}
204206
final String propertyName = ClassMultiReleaseExtension.shouldTransformToPropertyName(method)
@@ -232,9 +234,6 @@ private static boolean isSpecialCaseMethod(Class<?> clazz, Method m) {
232234
}
233235

234236
private static boolean isGetter(Method m) {
235-
if (ClassMultiReleaseExtension.isGetAccessorMethod(m)) {
236-
return true;
237-
}
238237
return (m.getName().startsWith(GET_PREFIX) || m.getName().startsWith(IS_PREFIX)) && m.getParameterCount() == 0;
239238
}
240239

src/main/java/org/eclipse/yasson/internal/properties/MessageKeys.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2022 Oracle and/or its affiliates. All rights reserved.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License v. 2.0 which is available at
@@ -60,6 +60,10 @@ public enum MessageKeys {
6060
* Class does not have default constructor.
6161
*/
6262
NO_DEFAULT_CONSTRUCTOR("noDefaultConstructor"),
63+
/**
64+
* Class does not have default constructor.
65+
*/
66+
RECORD_MULTIPLE_CONSTRUCTORS("recordMultipleConstructors"),
6367
/**
6468
* There has been an error while invoking getter.
6569
*/

src/main/java/org/eclipse/yasson/internal/serializer/ObjectDeserializer.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2021 Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2022 Oracle and/or its affiliates. All rights reserved.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License v. 2.0 which is available at
@@ -23,6 +23,7 @@
2323
import jakarta.json.bind.serializer.JsonbDeserializer;
2424
import jakarta.json.stream.JsonParser;
2525

26+
import org.eclipse.yasson.internal.ClassMultiReleaseExtension;
2627
import org.eclipse.yasson.internal.JsonbContext;
2728
import org.eclipse.yasson.internal.JsonbParser;
2829
import org.eclipse.yasson.internal.JsonbRiParser;
@@ -98,7 +99,8 @@ public T getInstance(Unmarshaller unmarshaller) {
9899
} else {
99100
Constructor<T> defaultConstructor = (Constructor<T>) getClassModel().getDefaultConstructor();
100101
if (defaultConstructor == null) {
101-
throw new JsonbException(Messages.getMessage(MessageKeys.NO_DEFAULT_CONSTRUCTOR, rawType));
102+
throw ClassMultiReleaseExtension.exceptionToThrow(rawType)
103+
.orElse(new JsonbException(Messages.getMessage(MessageKeys.NO_DEFAULT_CONSTRUCTOR, rawType)));
102104
}
103105
instance = ReflectionUtils.createNoArgConstructorInstance(defaultConstructor);
104106
}
Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2021, 2022 Oracle and/or its affiliates. All rights reserved.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License v. 2.0 which is available at
@@ -14,17 +14,21 @@
1414

1515
import java.lang.reflect.Constructor;
1616
import java.lang.reflect.Method;
17-
import java.util.Set;
17+
import java.util.Map;
18+
import java.util.Optional;
19+
20+
import jakarta.json.bind.JsonbException;
1821

1922
import org.eclipse.yasson.internal.model.JsonbCreator;
23+
import org.eclipse.yasson.internal.model.Property;
24+
import org.eclipse.yasson.internal.properties.MessageKeys;
25+
import org.eclipse.yasson.internal.properties.Messages;
2026

2127
/**
2228
* Search for instance creator from other sources.
2329
* Mainly intended to add extensibility for different java versions and new features.
2430
*/
25-
class ClassMultiReleaseExtension {
26-
27-
private static final Set<String> NOT_VALID_ACCESSOR_METHODS = Set.of("equals", "hashCode", "toString");
31+
public class ClassMultiReleaseExtension {
2832

2933
private ClassMultiReleaseExtension() {
3034
throw new IllegalStateException("This class cannot be instantiated");
@@ -34,18 +38,31 @@ static boolean shouldTransformToPropertyName(Method method) {
3438
return !method.getDeclaringClass().isRecord();
3539
}
3640

37-
static boolean isGetAccessorMethod(Method method) {
38-
if (method.getDeclaringClass().isRecord()) {
39-
return !NOT_VALID_ACCESSOR_METHODS.contains(method.getName());
40-
}
41-
return false;
41+
static boolean isSpecialAccessorMethod(Method method, Map<String, Property> classProperties) {
42+
return method.getDeclaringClass().isRecord()
43+
&& method.getParameterCount() == 0
44+
&& !void.class.equals(method.getReturnType())
45+
&& classProperties.containsKey(method.getName());
4246
}
4347

44-
static JsonbCreator findJsonbCreator(Class<?> clazz, Constructor<?>[] declaredConstructors, AnnotationIntrospector introspector) {
48+
static JsonbCreator findCreator(Class<?> clazz,
49+
Constructor<?>[] declaredConstructors,
50+
AnnotationIntrospector introspector) {
4551
if (clazz.isRecord()) {
46-
return introspector.createJsonbCreator(declaredConstructors[0], null, clazz);
52+
if (declaredConstructors.length == 1) {
53+
return introspector.createJsonbCreator(declaredConstructors[0], null, clazz);
54+
}
4755
}
4856
return null;
4957
}
5058

59+
public static Optional<JsonbException> exceptionToThrow(Class<?> clazz) {
60+
if (clazz.isRecord()) {
61+
if (clazz.getDeclaredConstructors().length > 1) {
62+
return Optional.of(new JsonbException(Messages.getMessage(MessageKeys.RECORD_MULTIPLE_CONSTRUCTORS, clazz)));
63+
}
64+
}
65+
return Optional.empty();
66+
}
67+
5168
}

src/main/resources/yasson-messages.properties

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#
2-
# Copyright (c) 2016, 2020 Oracle and/or its affiliates. All rights reserved.
2+
# Copyright (c) 2016, 2022 Oracle and/or its affiliates. All rights reserved.
33
#
44
# This program and the accompanying materials are made available under the
55
# terms of the Eclipse Public License v. 2.0 which is available at
@@ -50,6 +50,7 @@ dateTypeNotSupported=Date type not supported: {0}
5050
errorParsingDate=Error parsing {1} from value: {0}. Check your @JsonbDateFormat has all time units for {1} type, \
5151
or consider using org.eclipse.yasson.YassonConfig#ZERO_TIME_PARSE_DEFAULTING.
5252
noDefaultConstructor=Cannot create instance of a class: {0}, No default constructor found.
53+
recordMultipleConstructors=Cannot create instance of a record: {0}, Multiple constructors found.
5354
offsetDateTimeFromMillis=Parsing {0} from epoch millisecond, UTC zone offset will be used.
5455
timeToEpochMillisError=Cannot convert {0} to/from epoch milliseconds.
5556
configPropertyInvalidType=JsonbConfig property [{0}] must be of type [{1}].
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License v. 2.0 which is available at
6+
* http://www.eclipse.org/legal/epl-2.0,
7+
* or the Eclipse Distribution License v. 1.0 which is available at
8+
* http://www.eclipse.org/org/documents/edl-v10.php.
9+
*
10+
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
11+
*/
12+
13+
package org.eclipse.yasson.records;
14+
15+
import jakarta.json.bind.annotation.JsonbCreator;
16+
import jakarta.json.bind.annotation.JsonbProperty;
17+
18+
public record CarWithCreator(String type, String color) {
19+
20+
@JsonbCreator
21+
public static CarWithCreator create(@JsonbProperty("type") String type, @JsonbProperty("color") String color) {
22+
return new CarWithCreator(type, color);
23+
}
24+
25+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License v. 2.0 which is available at
6+
* http://www.eclipse.org/legal/epl-2.0,
7+
* or the Eclipse Distribution License v. 1.0 which is available at
8+
* http://www.eclipse.org/org/documents/edl-v10.php.
9+
*
10+
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
11+
*/
12+
13+
package org.eclipse.yasson.records;
14+
15+
public record CarWithExtraMethod(String type, String color) {
16+
17+
public String type() {
18+
return type;
19+
}
20+
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License v. 2.0 which is available at
6+
* http://www.eclipse.org/legal/epl-2.0,
7+
* or the Eclipse Distribution License v. 1.0 which is available at
8+
* http://www.eclipse.org/org/documents/edl-v10.php.
9+
*
10+
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
11+
*/
12+
13+
package org.eclipse.yasson.records;
14+
15+
public record CarWithMultipleConstructors(String type, String color) {
16+
17+
public CarWithMultipleConstructors(String type) {
18+
this(type, "red");
19+
}
20+
21+
}

0 commit comments

Comments
 (0)