Skip to content

Commit 8076a1a

Browse files
authored
Merge pull request #6 from Apaq/michael/apa-1157-fix-rest-patch-deserialize-issue
Adds modules for treenode resolving.
2 parents 34372e6 + eed6b4d commit 8076a1a

File tree

4 files changed

+117
-4
lines changed

4 files changed

+117
-4
lines changed

pom.xml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
<groupId>dk.apaq</groupId>
66
<artifactId>rest-patch</artifactId>
7-
<version>1.0.3-SNAPSHOT</version>
7+
<version>1.2.0-SNAPSHOT</version>
88
<packaging>jar</packaging>
99

1010
<properties>
@@ -26,7 +26,7 @@
2626
<dependency>
2727
<groupId>com.fasterxml.jackson.core</groupId>
2828
<artifactId>jackson-databind</artifactId>
29-
<version>2.15.2</version>
29+
<version>2.17.2</version>
3030
</dependency>
3131
<dependency>
3232
<groupId>org.slf4j</groupId>
@@ -59,8 +59,8 @@
5959
<groupId>org.apache.maven.plugins</groupId>
6060
<artifactId>maven-compiler-plugin</artifactId>
6161
<configuration>
62-
<source>11</source>
63-
<target>11</target>
62+
<source>17</source>
63+
<target>17</target>
6464
</configuration>
6565
</plugin>
6666
</plugins>
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package dk.apaq.rest.patch.jackson;
2+
3+
import com.fasterxml.jackson.core.JsonParser;
4+
import com.fasterxml.jackson.core.TreeNode;
5+
import com.fasterxml.jackson.databind.DeserializationContext;
6+
import com.fasterxml.jackson.databind.JsonDeserializer;
7+
import com.fasterxml.jackson.databind.deser.std.DelegatingDeserializer;
8+
import com.fasterxml.jackson.databind.node.TreeTraversingParser;
9+
10+
import java.io.IOException;
11+
12+
public class TreeNodeExtractorDeserializer extends DelegatingDeserializer {
13+
14+
public TreeNodeExtractorDeserializer(JsonDeserializer<?> defaultDeserializer) {
15+
super(defaultDeserializer);
16+
}
17+
18+
@Override
19+
protected JsonDeserializer<?> newDelegatingInstance(JsonDeserializer<?> newDelegate) {
20+
return new TreeNodeExtractorDeserializer(newDelegate);
21+
}
22+
23+
@Override
24+
public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
25+
var context = p.getParsingContext();
26+
var depth = context.getNestingDepth();
27+
28+
if(depth == 1 && !(p instanceof TreeTraversingParser)) {
29+
// Extract the JSON tree
30+
TreeNode treeNode = p.readValueAsTree();
31+
TreeNodeHolder.set(treeNode);
32+
33+
// Re-parse the tree node to get the actual object
34+
JsonParser treeParser = treeNode.traverse(ctxt.getParser().getCodec());
35+
if(treeParser.getCurrentToken() == null)
36+
treeParser.nextToken();
37+
return super.deserialize(treeParser, ctxt);
38+
} else {
39+
return super.deserialize(p, ctxt);
40+
}
41+
}
42+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package dk.apaq.rest.patch.jackson;
2+
3+
import com.fasterxml.jackson.databind.BeanDescription;
4+
import com.fasterxml.jackson.databind.DeserializationConfig;
5+
import com.fasterxml.jackson.databind.JsonDeserializer;
6+
import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier;
7+
import com.fasterxml.jackson.databind.module.SimpleModule;
8+
9+
public class TreeNodeExtractorModule extends SimpleModule {
10+
11+
@Override
12+
public void setupModule(SetupContext context) {
13+
super.setupModule(context);
14+
context.addBeanDeserializerModifier(new BeanDeserializerModifier() {
15+
@Override
16+
public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config,
17+
BeanDescription beanDesc,
18+
JsonDeserializer<?> deserializer) {
19+
return new TreeNodeExtractorDeserializer(deserializer);
20+
}
21+
22+
23+
});
24+
}
25+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package dk.apaq.rest.patch.jackson;
2+
3+
import dk.apaq.rest.patch.DummyEntity;
4+
import org.junit.Test;
5+
6+
import com.fasterxml.jackson.databind.ObjectMapper;
7+
8+
import static org.junit.Assert.*;
9+
10+
import java.io.IOException;
11+
import java.util.Arrays;
12+
import java.util.Collections;
13+
14+
public class TreeNodeExtractorModuleTest {
15+
16+
private TreeNodeExtractorModule module = new TreeNodeExtractorModule();
17+
private TreeNodePropertyReferenceConverter converter = new TreeNodePropertyReferenceConverter();
18+
19+
@Test
20+
public void testTreeNodeResolvesField() throws IOException {
21+
var mapper = new ObjectMapper();
22+
mapper.registerModule(module);
23+
DummyEntity de = mapper.readValue("{\"text\": \"qwerty\"}", DummyEntity.class);
24+
Iterable<String> fields = converter.translate(TreeNodeHolder.get());
25+
assertEquals(Collections.singletonList("text"), fields);
26+
}
27+
28+
@Test
29+
public void testTreeNodeResolvesChildField() throws IOException {
30+
var mapper = new ObjectMapper();
31+
mapper.registerModule(module);
32+
DummyEntity de = mapper.readValue("{\"child\": {\"text\":\"qwerty\"}}", DummyEntity.class);
33+
Iterable<String> fields = converter.translate(TreeNodeHolder.get());
34+
assertEquals(Collections.singletonList("child.text"), fields);
35+
}
36+
37+
@Test
38+
public void testTreeNodeResolvedWithReaderFor() throws IOException {
39+
var json = "{\"text\": \"value\", \"child\": {\"text\":\"qwerty\", \"list\":[\"Karl\"],\"child\": {\"text\":\"value\"}}}";
40+
var mapper = new ObjectMapper();
41+
mapper.registerModule(module);
42+
DummyEntity de = mapper.readerFor(DummyEntity.class).readValue(json, DummyEntity.class);
43+
Iterable<String> fields = converter.translate(TreeNodeHolder.get());
44+
assertEquals(Arrays.asList("text", "child.text", "child.list", "child.child.text"), fields);
45+
}
46+
}

0 commit comments

Comments
 (0)