Skip to content

Commit e62eb14

Browse files
committed
Jackson (de)serialization support [Closes #2]
1 parent 757b72b commit e62eb14

File tree

6 files changed

+174
-23
lines changed

6 files changed

+174
-23
lines changed

modules/typed-ids/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ dependencies {
1717
compileOnly(libs.jackson.databind)
1818

1919
testImplementation(project(":typed-ids-testing"))
20+
testImplementation(libs.jackson.databind)
2021
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
2122
}
2223

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
package org.framefork.typedIds.bigint.json.jackson;
22

33
import com.fasterxml.jackson.core.Version;
4+
import com.fasterxml.jackson.databind.BeanDescription;
5+
import com.fasterxml.jackson.databind.JavaType;
6+
import com.fasterxml.jackson.databind.JsonSerializer;
47
import com.fasterxml.jackson.databind.Module;
5-
import com.fasterxml.jackson.databind.module.SimpleDeserializers;
6-
import com.fasterxml.jackson.databind.module.SimpleSerializers;
8+
import com.fasterxml.jackson.databind.SerializationConfig;
9+
import com.fasterxml.jackson.databind.ser.Serializers;
710
import com.google.auto.service.AutoService;
811
import org.framefork.typedIds.bigint.ObjectBigIntIdTypeUtils;
12+
import org.jspecify.annotations.Nullable;
913

1014
@AutoService(Module.class)
1115
public class ObjectBigIntIdJacksonModule extends Module
@@ -26,22 +30,28 @@ public Version version()
2630
@Override
2731
public void setupModule(final SetupContext context)
2832
{
29-
context.addSerializers(getSerializers());
30-
context.addDeserializers(getDeserializers());
33+
context.addSerializers(new ObjectUuidSerializers());
34+
// Jackson is capable of deserializing the long, and then using the primary constructor without any additional help
3135
}
3236

33-
private static SimpleSerializers getSerializers()
37+
private static final class ObjectUuidSerializers extends Serializers.Base
3438
{
35-
var serializers = new SimpleSerializers();
3639

37-
serializers.addSerializer(ObjectBigIntIdTypeUtils.getObjectBigIntIdRawClass(), new ObjectBigIntIdSerializer());
40+
@Nullable
41+
@Override
42+
public JsonSerializer<?> findSerializer(
43+
final SerializationConfig config,
44+
final JavaType type,
45+
final BeanDescription beanDesc
46+
)
47+
{
48+
if (ObjectBigIntIdTypeUtils.getObjectBigIntIdRawClass().isAssignableFrom(type.getRawClass())) {
49+
return new ObjectBigIntIdSerializer();
50+
}
51+
52+
return null;
53+
}
3854

39-
return serializers;
40-
}
41-
42-
private static SimpleDeserializers getDeserializers()
43-
{
44-
return new SimpleDeserializers();
4555
}
4656

4757
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package org.framefork.typedIds.uuid.json.jackson;
2+
3+
import com.fasterxml.jackson.core.JsonParser;
4+
import com.fasterxml.jackson.databind.DeserializationContext;
5+
import com.fasterxml.jackson.databind.JsonDeserializer;
6+
import org.framefork.typedIds.common.ReflectionHacks;
7+
import org.framefork.typedIds.uuid.ObjectUuid;
8+
import org.framefork.typedIds.uuid.ObjectUuidTypeUtils;
9+
10+
import java.io.IOException;
11+
import java.lang.invoke.MethodHandle;
12+
import java.util.UUID;
13+
14+
public class ObjectUuidDeserializer extends JsonDeserializer<ObjectUuid<?>>
15+
{
16+
17+
private final MethodHandle constructor;
18+
19+
public ObjectUuidDeserializer(final Class<?> identifierClass)
20+
{
21+
if (!ObjectUuid.class.isAssignableFrom(identifierClass)) {
22+
throw new IllegalArgumentException("Type %s is not a subtype of %s".formatted(identifierClass, ObjectUuid.class));
23+
}
24+
25+
this.constructor = ReflectionHacks.getMainConstructor(identifierClass, UUID.class);
26+
}
27+
28+
@Override
29+
public ObjectUuid<?> deserialize(
30+
final JsonParser parser,
31+
final DeserializationContext context
32+
) throws
33+
IOException
34+
{
35+
var stringUuid = parser.getValueAsString();
36+
var uuid = UUID.fromString(stringUuid);
37+
38+
return ObjectUuidTypeUtils.wrapUuidToIdentifier(uuid, constructor);
39+
}
40+
41+
}

modules/typed-ids/src/main/java/org/framefork/typedIds/uuid/json/jackson/ObjectUuidJacksonModule.java

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
package org.framefork.typedIds.uuid.json.jackson;
22

33
import com.fasterxml.jackson.core.Version;
4+
import com.fasterxml.jackson.databind.BeanDescription;
5+
import com.fasterxml.jackson.databind.DeserializationConfig;
6+
import com.fasterxml.jackson.databind.JavaType;
7+
import com.fasterxml.jackson.databind.JsonDeserializer;
8+
import com.fasterxml.jackson.databind.JsonSerializer;
49
import com.fasterxml.jackson.databind.Module;
5-
import com.fasterxml.jackson.databind.module.SimpleDeserializers;
6-
import com.fasterxml.jackson.databind.module.SimpleSerializers;
10+
import com.fasterxml.jackson.databind.SerializationConfig;
11+
import com.fasterxml.jackson.databind.deser.Deserializers;
12+
import com.fasterxml.jackson.databind.ser.Serializers;
713
import com.google.auto.service.AutoService;
814
import org.framefork.typedIds.uuid.ObjectUuidTypeUtils;
15+
import org.jspecify.annotations.Nullable;
916

1017
@AutoService(Module.class)
1118
public class ObjectUuidJacksonModule extends Module
@@ -26,22 +33,48 @@ public Version version()
2633
@Override
2734
public void setupModule(final SetupContext context)
2835
{
29-
context.addSerializers(getSerializers());
30-
context.addDeserializers(getDeserializers());
36+
context.addSerializers(new ObjectUuidSerializers());
37+
context.addDeserializers(new ObjectUuidDeserializers());
3138
}
3239

33-
private static SimpleSerializers getSerializers()
40+
private static final class ObjectUuidSerializers extends Serializers.Base
3441
{
35-
var serializers = new SimpleSerializers();
3642

37-
serializers.addSerializer(ObjectUuidTypeUtils.getObjectUuidRawClass(), new ObjectUuidSerializer());
43+
@Nullable
44+
@Override
45+
public JsonSerializer<?> findSerializer(
46+
final SerializationConfig config,
47+
final JavaType type,
48+
final BeanDescription beanDesc
49+
)
50+
{
51+
if (ObjectUuidTypeUtils.getObjectUuidRawClass().isAssignableFrom(type.getRawClass())) {
52+
return new ObjectUuidSerializer();
53+
}
54+
55+
return null;
56+
}
3857

39-
return serializers;
4058
}
4159

42-
private static SimpleDeserializers getDeserializers()
60+
private static final class ObjectUuidDeserializers extends Deserializers.Base
4361
{
44-
return new SimpleDeserializers();
62+
63+
@Nullable
64+
@Override
65+
public JsonDeserializer<?> findBeanDeserializer(
66+
final JavaType type,
67+
final DeserializationConfig config,
68+
final BeanDescription beanDesc
69+
)
70+
{
71+
if (ObjectUuidTypeUtils.getObjectUuidRawClass().isAssignableFrom(type.getRawClass())) {
72+
return new ObjectUuidDeserializer(type.getRawClass());
73+
}
74+
75+
return null;
76+
}
77+
4578
}
4679

4780
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package org.framefork.typedIds.bigint.json.jackson;
2+
3+
import com.fasterxml.jackson.databind.ObjectMapper;
4+
import org.framefork.typedIds.bigint.ObjectBigIntIdMock;
5+
import org.junit.jupiter.api.Test;
6+
7+
import static org.assertj.core.api.Assertions.assertThat;
8+
9+
class ObjectBigIntIdJacksonModuleTest
10+
{
11+
12+
private final ObjectMapper objectMapper = new ObjectMapper()
13+
.registerModule(new ObjectBigIntIdJacksonModule());
14+
15+
@Test
16+
public void functional() throws Exception
17+
{
18+
var id42 = ObjectBigIntIdMock.from("42");
19+
var originalDto = new Dto(id42);
20+
21+
var dtoJson = objectMapper.writeValueAsString(originalDto);
22+
assertThat(dtoJson).isEqualTo("{\"id\":42}");
23+
24+
var deserializedDto = objectMapper.readValue(dtoJson, Dto.class);
25+
assertThat(deserializedDto).isEqualTo(originalDto);
26+
}
27+
28+
record Dto(ObjectBigIntIdMock id)
29+
{
30+
31+
}
32+
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package org.framefork.typedIds.uuid.json.jackson;
2+
3+
import com.fasterxml.jackson.databind.ObjectMapper;
4+
import org.framefork.typedIds.uuid.ObjectUuidMock;
5+
import org.junit.jupiter.api.Test;
6+
7+
import static org.assertj.core.api.Assertions.assertThat;
8+
9+
class ObjectUuidJacksonModuleTest
10+
{
11+
12+
private final ObjectMapper objectMapper = new ObjectMapper()
13+
.registerModule(new ObjectUuidJacksonModule());
14+
15+
@Test
16+
public void functional() throws Exception
17+
{
18+
var id33 = ObjectUuidMock.from("33a7641c-811e-40b7-986e-ad109cfcf220");
19+
var originalDto = new Dto(id33);
20+
21+
var dtoJson = objectMapper.writeValueAsString(originalDto);
22+
assertThat(dtoJson).isEqualTo("{\"id\":\"33a7641c-811e-40b7-986e-ad109cfcf220\"}");
23+
24+
var deserializedDto = objectMapper.readValue(dtoJson, Dto.class);
25+
assertThat(deserializedDto).isEqualTo(originalDto);
26+
}
27+
28+
record Dto(ObjectUuidMock id)
29+
{
30+
31+
}
32+
33+
}

0 commit comments

Comments
 (0)