Skip to content

Commit d7e77ef

Browse files
committed
[Enhancement #37] Refactor deserialization to use the Jakarta JSON API.
1 parent 0399389 commit d7e77ef

28 files changed

+601
-406
lines changed

pom.xml

+8-2
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@
3434
<version>${cz.cvut.kbss.jopa.version}</version>
3535
</dependency>
3636
<dependency>
37-
<groupId>org.glassfish</groupId>
38-
<artifactId>jakarta.json</artifactId>
37+
<groupId>jakarta.json</groupId>
38+
<artifactId>jakarta.json-api</artifactId>
3939
<version>2.0.1</version>
4040
</dependency>
4141

@@ -90,6 +90,12 @@
9090
<version>1.3.2</version>
9191
<scope>test</scope>
9292
</dependency>
93+
<dependency>
94+
<groupId>org.glassfish</groupId>
95+
<artifactId>jakarta.json</artifactId>
96+
<version>2.0.1</version>
97+
<scope>test</scope>
98+
</dependency>
9399
<dependency>
94100
<groupId>ch.qos.logback</groupId>
95101
<artifactId>logback-classic</artifactId>

src/main/java/cz/cvut/kbss/jsonld/deserialization/datetime/DurationDeserializer.java

+3-5
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,12 @@
22

33
import cz.cvut.kbss.jsonld.deserialization.DeserializationContext;
44
import cz.cvut.kbss.jsonld.deserialization.ValueDeserializer;
5+
import cz.cvut.kbss.jsonld.deserialization.util.ValueUtils;
56
import cz.cvut.kbss.jsonld.exception.JsonLdDeserializationException;
6-
import jakarta.json.JsonObject;
77
import jakarta.json.JsonValue;
88

99
import java.time.Duration;
1010

11-
import static cz.cvut.kbss.jsonld.deserialization.datetime.OffsetDateTimeDeserializer.getLiteralValue;
12-
1311
/**
1412
* Deserializes JSON values to {@link Duration}.
1513
* <p>
@@ -19,9 +17,9 @@ public class DurationDeserializer implements ValueDeserializer<Duration> {
1917

2018
@Override
2119
public Duration deserialize(JsonValue jsonNode, DeserializationContext<Duration> ctx) {
22-
final Object value = getLiteralValue(jsonNode);
20+
final JsonValue value = ValueUtils.getValue(jsonNode);
2321
try {
24-
return Duration.parse(value.toString());
22+
return Duration.parse(ValueUtils.stringValue(value));
2523
} catch (RuntimeException e) {
2624
throw new JsonLdDeserializationException("Unable to deserialize duration.", e);
2725
}

src/main/java/cz/cvut/kbss/jsonld/deserialization/datetime/LocalDateDeserializer.java

+3-4
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,12 @@
33
import cz.cvut.kbss.jopa.datatype.xsd.XsdDateMapper;
44
import cz.cvut.kbss.jsonld.deserialization.DeserializationContext;
55
import cz.cvut.kbss.jsonld.deserialization.ValueDeserializer;
6+
import cz.cvut.kbss.jsonld.deserialization.util.ValueUtils;
67
import cz.cvut.kbss.jsonld.exception.JsonLdDeserializationException;
78
import jakarta.json.JsonValue;
89

910
import java.time.LocalDate;
1011

11-
import static cz.cvut.kbss.jsonld.deserialization.datetime.OffsetDateTimeDeserializer.getLiteralValue;
12-
1312
/**
1413
* Deserializes values to {@link LocalDate}.
1514
* <p>
@@ -19,9 +18,9 @@ public class LocalDateDeserializer implements ValueDeserializer<LocalDate> {
1918

2019
@Override
2120
public LocalDate deserialize(JsonValue jsonNode, DeserializationContext<LocalDate> ctx) {
22-
final Object value = getLiteralValue(jsonNode);
21+
final JsonValue value = ValueUtils.getValue(jsonNode);
2322
try {
24-
return XsdDateMapper.map(value.toString());
23+
return XsdDateMapper.map(ValueUtils.stringValue(value));
2524
} catch (RuntimeException e) {
2625
throw new JsonLdDeserializationException("Unable to deserialize date value.", e);
2726
}

src/main/java/cz/cvut/kbss/jsonld/deserialization/datetime/OffsetDateTimeDeserializer.java

+5-13
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
package cz.cvut.kbss.jsonld.deserialization.datetime;
22

33
import cz.cvut.kbss.jsonld.Configuration;
4-
import cz.cvut.kbss.jsonld.JsonLd;
54
import cz.cvut.kbss.jsonld.deserialization.DeserializationContext;
65
import cz.cvut.kbss.jsonld.deserialization.ValueDeserializer;
6+
import cz.cvut.kbss.jsonld.deserialization.util.ValueUtils;
77
import cz.cvut.kbss.jsonld.exception.JsonLdDeserializationException;
88
import jakarta.json.JsonNumber;
99
import jakarta.json.JsonValue;
@@ -13,8 +13,8 @@
1313
/**
1414
* Deserializes values to {@link OffsetDateTime}.
1515
* <p>
16-
* If the value is a number, it is taken as the number of milliseconds since the Unix Epoch. Otherwise, it is parsed as a
17-
* string.
16+
* If the value is a number, it is taken as the number of milliseconds since the Unix Epoch. Otherwise, it is parsed as
17+
* a string.
1818
* <p>
1919
* If a datetime pattern is configured ({@link cz.cvut.kbss.jsonld.ConfigParam#DATE_TIME_FORMAT}), it is used to parse
2020
* the value. Otherwise, the default ISO-based pattern is used.
@@ -27,23 +27,15 @@ public class OffsetDateTimeDeserializer implements ValueDeserializer<OffsetDateT
2727

2828
@Override
2929
public OffsetDateTime deserialize(JsonValue jsonNode, DeserializationContext<OffsetDateTime> ctx) {
30-
final JsonValue value = getLiteralValue(jsonNode);
30+
final JsonValue value = ValueUtils.getValue(jsonNode);
3131
try {
3232
return value.getValueType() == JsonValue.ValueType.NUMBER ? epochResolver.resolve((JsonNumber) value) :
33-
stringResolver.resolve(value.toString());
33+
stringResolver.resolve(ValueUtils.stringValue(value));
3434
} catch (RuntimeException e) {
3535
throw new JsonLdDeserializationException("Unable to deserialize datetime value.", e);
3636
}
3737
}
3838

39-
static JsonValue getLiteralValue(JsonValue jsonNode) {
40-
if (jsonNode.getValueType() != JsonValue.ValueType.OBJECT || !jsonNode.asJsonObject().containsKey(JsonLd.VALUE)) {
41-
throw new JsonLdDeserializationException("Cannot deserialize node " + jsonNode + "as literal. " +
42-
"It is missing attribute '" + JsonLd.VALUE + "'.");
43-
}
44-
return jsonNode.asJsonObject().get(JsonLd.VALUE);
45-
}
46-
4739
@Override
4840
public void configure(Configuration config) {
4941
stringResolver.configure(config);

src/main/java/cz/cvut/kbss/jsonld/deserialization/datetime/OffsetTimeDeserializer.java

+3-4
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,12 @@
33
import cz.cvut.kbss.jopa.datatype.xsd.XsdTimeMapper;
44
import cz.cvut.kbss.jsonld.deserialization.DeserializationContext;
55
import cz.cvut.kbss.jsonld.deserialization.ValueDeserializer;
6+
import cz.cvut.kbss.jsonld.deserialization.util.ValueUtils;
67
import cz.cvut.kbss.jsonld.exception.JsonLdDeserializationException;
78
import jakarta.json.JsonValue;
89

910
import java.time.OffsetTime;
1011

11-
import static cz.cvut.kbss.jsonld.deserialization.datetime.OffsetDateTimeDeserializer.getLiteralValue;
12-
1312
/**
1413
* Deserializes values to {@link OffsetTime}.
1514
* <p>
@@ -19,9 +18,9 @@ public class OffsetTimeDeserializer implements ValueDeserializer<OffsetTime> {
1918

2019
@Override
2120
public OffsetTime deserialize(JsonValue jsonNode, DeserializationContext<OffsetTime> ctx) {
22-
final JsonValue value = getLiteralValue(jsonNode);
21+
final JsonValue value = ValueUtils.getValue(jsonNode);
2322
try {
24-
return XsdTimeMapper.map(value.toString());
23+
return XsdTimeMapper.map(ValueUtils.stringValue(value));
2524
} catch (RuntimeException e) {
2625
throw new JsonLdDeserializationException("Unable to deserialize time value.", e);
2726
}

src/main/java/cz/cvut/kbss/jsonld/deserialization/datetime/PeriodDeserializer.java

+3-4
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@
22

33
import cz.cvut.kbss.jsonld.deserialization.DeserializationContext;
44
import cz.cvut.kbss.jsonld.deserialization.ValueDeserializer;
5+
import cz.cvut.kbss.jsonld.deserialization.util.ValueUtils;
56
import cz.cvut.kbss.jsonld.exception.JsonLdDeserializationException;
67
import jakarta.json.JsonValue;
78

89
import java.time.Period;
910

10-
import static cz.cvut.kbss.jsonld.deserialization.datetime.OffsetDateTimeDeserializer.getLiteralValue;
11-
1211
/**
1312
* Deserializes JSON values to {@link Period}.
1413
* <p>
@@ -18,9 +17,9 @@ public class PeriodDeserializer implements ValueDeserializer<Period> {
1817

1918
@Override
2019
public Period deserialize(JsonValue jsonNode, DeserializationContext<Period> ctx) {
21-
final JsonValue value = getLiteralValue(jsonNode);
20+
final JsonValue value = ValueUtils.getValue(jsonNode);
2221
try {
23-
return Period.parse(value.toString());
22+
return Period.parse(ValueUtils.stringValue(value));
2423
} catch (RuntimeException e) {
2524
throw new JsonLdDeserializationException("Unable to deserialize duration.", e);
2625
}

src/main/java/cz/cvut/kbss/jsonld/deserialization/expanded/CollectionDeserializer.java

+31-29
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,16 @@
1717
import cz.cvut.kbss.jsonld.deserialization.InstanceBuilder;
1818
import cz.cvut.kbss.jsonld.deserialization.util.DataTypeTransformer;
1919
import cz.cvut.kbss.jsonld.deserialization.util.LangString;
20+
import cz.cvut.kbss.jsonld.deserialization.util.ValueUtils;
2021
import cz.cvut.kbss.jsonld.deserialization.util.XSDTypeCoercer;
2122
import cz.cvut.kbss.jsonld.exception.MissingIdentifierException;
23+
import jakarta.json.JsonArray;
24+
import jakarta.json.JsonObject;
25+
import jakarta.json.JsonValue;
2226

2327
import java.net.URI;
24-
import java.util.List;
25-
import java.util.Map;
2628

27-
class CollectionDeserializer extends Deserializer<List<?>> {
29+
class CollectionDeserializer extends Deserializer<JsonArray> {
2830

2931
private final String property;
3032

@@ -34,58 +36,58 @@ class CollectionDeserializer extends Deserializer<List<?>> {
3436
}
3537

3638
@Override
37-
void processValue(List<?> value) {
38-
if (value.size() == 1 && value.get(0) instanceof Map) {
39-
final Map<?, ?> map = (Map<?, ?>) value.get(0);
39+
void processValue(JsonArray value) {
40+
if (value.size() == 1 && value.get(0).getValueType() == JsonValue.ValueType.OBJECT) {
41+
final JsonObject obj = value.getJsonObject(0);
4042
if (!instanceBuilder.isPlural(property)) {
41-
resolvePropertyValue(map);
43+
resolvePropertyValue(obj);
4244
return;
4345
}
44-
if (map.size() == 1 && map.containsKey(JsonLd.LIST)) {
45-
assert map.get(JsonLd.LIST) instanceof List;
46-
processValue((List<?>) map.get(JsonLd.LIST));
46+
if (obj.size() == 1 && obj.containsKey(JsonLd.LIST)) {
47+
assert obj.get(JsonLd.LIST).getValueType() == JsonValue.ValueType.ARRAY;
48+
processValue(obj.getJsonArray(JsonLd.LIST));
4749
return;
4850
}
4951
}
5052
instanceBuilder.openCollection(property);
51-
for (Object item : value) {
52-
if (item instanceof Map) {
53-
resolveValue((Map<?, ?>) item);
53+
for (JsonValue item : value) {
54+
if (item.getValueType() == JsonValue.ValueType.OBJECT) {
55+
resolveValue(item.asJsonObject());
5456
} else {
55-
instanceBuilder.addValue(item);
57+
instanceBuilder.addValue(ValueUtils.literalValue(item));
5658
}
5759
}
5860
instanceBuilder.closeCollection();
5961
}
6062

61-
private void resolveValue(Map<?, ?> value) {
63+
private void resolveValue(JsonObject value) {
6264
final Class<?> targetType = instanceBuilder.getCurrentCollectionElementType();
6365
if (config.getDeserializers().hasCustomDeserializer(targetType)) {
6466
instanceBuilder.addValue(deserializeUsingCustomDeserializer(targetType, value));
6567
} else if (value.size() == 1 && value.containsKey(JsonLd.VALUE)) {
66-
instanceBuilder.addValue(value.get(JsonLd.VALUE));
68+
instanceBuilder.addValue(ValueUtils.literalValue(ValueUtils.getValue(value)));
6769
} else if (value.size() == 1 && value.containsKey(JsonLd.ID)) {
6870
handleReferenceNodeInCollection(value, targetType);
6971
} else if (value.containsKey(JsonLd.LANGUAGE)) {
7072
assert value.containsKey(JsonLd.VALUE);
7173
instanceBuilder.addValue(
72-
new LangString(value.get(JsonLd.VALUE).toString(), value.get(JsonLd.LANGUAGE).toString()));
74+
new LangString(ValueUtils.stringValue(ValueUtils.getValue(value)), ValueUtils.stringValue(value.get(JsonLd.LANGUAGE))));
7375
} else if (instanceBuilder.isCurrentCollectionProperties()) {
7476
// If we are deserializing an object into @Properties, just extract the identifier and put it into the map
7577
if (!value.containsKey(JsonLd.ID)) {
7678
throw new MissingIdentifierException(
7779
"Cannot put an object without an identifier into @Properties. Object: " + value);
7880
}
79-
instanceBuilder.addValue(URI.create(value.get(JsonLd.ID).toString()));
81+
instanceBuilder.addValue(URI.create(ValueUtils.stringValue(value.get(JsonLd.ID))));
8082
} else {
8183
final Class<?> elementType = instanceBuilder.getCurrentCollectionElementType();
8284
new ObjectDeserializer(instanceBuilder, config, elementType).processValue(value);
8385
}
8486
}
8587

86-
private void handleReferenceNodeInCollection(Map<?, ?> value, Class<?> targetType) {
88+
private void handleReferenceNodeInCollection(JsonObject value, Class<?> targetType) {
8789
assert value.size() == 1 && value.containsKey(JsonLd.ID);
88-
final String identifier = value.get(JsonLd.ID).toString();
90+
final String identifier = ValueUtils.stringValue(value.get(JsonLd.ID));
8991
if (targetType.isEnum()) {
9092
instanceBuilder.addValue(DataTypeTransformer.transformIndividualToEnumConstant(identifier,
9193
(Class<? extends Enum>) targetType));
@@ -94,7 +96,7 @@ private void handleReferenceNodeInCollection(Map<?, ?> value, Class<?> targetTyp
9496
}
9597
}
9698

97-
private void resolvePropertyValue(Map<?, ?> value) {
99+
private void resolvePropertyValue(JsonObject value) {
98100
final Class<?> targetType = instanceBuilder.getTargetType(property);
99101
if (config.getDeserializers().hasCustomDeserializer(targetType)) {
100102
instanceBuilder.addValue(property, deserializeUsingCustomDeserializer(targetType, value));
@@ -109,27 +111,27 @@ private void resolvePropertyValue(Map<?, ?> value) {
109111
}
110112
}
111113

112-
private <T> T deserializeUsingCustomDeserializer(Class<T> targetType, Map<?, ?> value) {
114+
private <T> T deserializeUsingCustomDeserializer(Class<T> targetType, JsonObject value) {
113115
final DeserializationContext<T> ctx = new DeserializationContext<>(targetType, config.getTargetResolver());
114116
assert config.getDeserializers().getDeserializer(ctx).isPresent();
115117
return config.getDeserializers().getDeserializer(ctx).get().deserialize(value, ctx);
116118
}
117119

118-
private void extractLiteralValue(Map<?, ?> value) {
119-
final Object val = value.get(JsonLd.VALUE);
120+
private void extractLiteralValue(JsonObject value) {
121+
final JsonValue val = value.get(JsonLd.VALUE);
120122
if (value.containsKey(JsonLd.TYPE)) {
121123
instanceBuilder
122-
.addValue(property, XSDTypeCoercer.coerceType(val.toString(), value.get(JsonLd.TYPE).toString()));
124+
.addValue(property, XSDTypeCoercer.coerceType(ValueUtils.stringValue(val), ValueUtils.stringValue(value.get(JsonLd.TYPE))));
123125
} else if (value.containsKey(JsonLd.LANGUAGE)) {
124-
instanceBuilder.addValue(property, new LangString(val.toString(), value.get(JsonLd.LANGUAGE).toString()));
126+
instanceBuilder.addValue(property, new LangString(ValueUtils.stringValue(val), ValueUtils.stringValue(value.get(JsonLd.LANGUAGE))));
125127
} else {
126-
instanceBuilder.addValue(property, val);
128+
instanceBuilder.addValue(property, ValueUtils.literalValue(val));
127129
}
128130
}
129131

130-
private void handleSingularReferenceNode(Map<?, ?> value, Class<?> targetType) {
132+
private void handleSingularReferenceNode(JsonObject value, Class<?> targetType) {
131133
assert value.size() == 1 && value.containsKey(JsonLd.ID);
132-
final String identifier = value.get(JsonLd.ID).toString();
134+
final String identifier = ValueUtils.stringValue(value.get(JsonLd.ID));
133135
if (targetType.isEnum()) {
134136
instanceBuilder.addValue(property, DataTypeTransformer.transformIndividualToEnumConstant(identifier,
135137
(Class<? extends Enum>) targetType));

src/main/java/cz/cvut/kbss/jsonld/deserialization/expanded/Deserializer.java

+18-18
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,28 @@
11
/**
22
* Copyright (C) 2022 Czech Technical University in Prague
3-
*
4-
* This program is free software: you can redistribute it and/or modify it under
5-
* the terms of the GNU General Public License as published by the Free Software
6-
* Foundation, either version 3 of the License, or (at your option) any
7-
* later version.
8-
*
9-
* This program is distributed in the hope that it will be useful, but WITHOUT
10-
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11-
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12-
* details. You should have received a copy of the GNU General Public License
13-
* along with this program. If not, see <http://www.gnu.org/licenses/>.
3+
* <p>
4+
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
5+
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
6+
* version.
7+
* <p>
8+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
9+
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
10+
* details. You should have received a copy of the GNU General Public License along with this program. If not, see
11+
* <http://www.gnu.org/licenses/>.
1412
*/
1513
package cz.cvut.kbss.jsonld.deserialization.expanded;
1614

1715
import cz.cvut.kbss.jsonld.Configuration;
1816
import cz.cvut.kbss.jsonld.JsonLd;
1917
import cz.cvut.kbss.jsonld.common.BeanClassProcessor;
2018
import cz.cvut.kbss.jsonld.deserialization.InstanceBuilder;
19+
import cz.cvut.kbss.jsonld.deserialization.util.ValueUtils;
20+
import jakarta.json.JsonObject;
21+
import jakarta.json.JsonValue;
2122

2223
import java.util.Collections;
2324
import java.util.List;
24-
import java.util.Map;
25+
import java.util.stream.Collectors;
2526

2627
abstract class Deserializer<X> {
2728

@@ -37,22 +38,21 @@ Configuration configuration() {
3738
return config.getConfiguration();
3839
}
3940

40-
<T> Class<? extends T> resolveTargetClass(Object jsonRoot, Class<T> resultClass) {
41+
<T> Class<? extends T> resolveTargetClass(JsonObject jsonRoot, Class<T> resultClass) {
4142
if (BeanClassProcessor.isIdentifierType(resultClass)) {
4243
return resultClass;
4344
}
4445
final List<String> types = getObjectTypes(jsonRoot);
4546
return config.getTargetResolver().getTargetClass(resultClass, types);
4647
}
4748

48-
List<String> getObjectTypes(Object jsonLdObject) {
49-
assert jsonLdObject instanceof Map;
50-
final Object types = ((Map<?, ?>) jsonLdObject).get(JsonLd.TYPE);
49+
List<String> getObjectTypes(JsonObject jsonLdObject) {
50+
final JsonValue types = jsonLdObject.get(JsonLd.TYPE);
5151
if (types == null) {
5252
return Collections.emptyList();
5353
}
54-
assert types instanceof List;
55-
return (List<String>) types;
54+
assert types.getValueType() == JsonValue.ValueType.ARRAY;
55+
return types.asJsonArray().stream().map(ValueUtils::stringValue).collect(Collectors.toList());
5656
}
5757

5858
abstract void processValue(X value);

0 commit comments

Comments
 (0)