Skip to content

Commit be8601c

Browse files
author
timothy-volvo
authored
Add support for @JSONVIEW (#37)
* Add Unit Test reproducing JsonView serialization issue and confirming deserialization works as expected * Add support for @JSONVIEW #33
1 parent 477c3d3 commit be8601c

File tree

3 files changed

+429
-10
lines changed

3 files changed

+429
-10
lines changed

src/main/java/io/openapitools/jackson/dataformat/hal/ser/HALBeanSerializer.java

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.fasterxml.jackson.core.JsonToken;
55
import com.fasterxml.jackson.core.type.WritableTypeId;
66
import com.fasterxml.jackson.databind.BeanDescription;
7+
import com.fasterxml.jackson.databind.MapperFeature;
78
import com.fasterxml.jackson.databind.SerializerProvider;
89
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
910
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
@@ -16,15 +17,8 @@
1617
import io.openapitools.jackson.dataformat.hal.annotation.EmbeddedResource;
1718
import io.openapitools.jackson.dataformat.hal.annotation.Link;
1819
import java.io.IOException;
19-
import java.util.ArrayList;
20-
import java.util.Arrays;
21-
import java.util.Collection;
22-
import java.util.HashSet;
23-
import java.util.List;
24-
import java.util.Map;
25-
import java.util.Set;
26-
import java.util.TreeMap;
27-
import java.util.TreeSet;
20+
import java.util.*;
21+
import java.util.stream.Collectors;
2822

2923
import org.slf4j.Logger;
3024
import org.slf4j.LoggerFactory;
@@ -110,7 +104,23 @@ public FilteredProperties(Object bean, SerializerProvider provider,
110104

111105
populateCurieMap(beanDescription);
112106

113-
for (BeanPropertyWriter prop : _props) {
107+
BeanPropertyWriter[] props;
108+
109+
110+
if (_filteredProps != null && provider.getActiveView() != null) {
111+
props = Arrays.stream(_filteredProps).filter(bpw -> {
112+
113+
if (bpw == null || bpw.getViews() == null || bpw.getViews().length == 0) {
114+
return provider.getConfig().isEnabled(MapperFeature.DEFAULT_VIEW_INCLUSION);
115+
}
116+
117+
return Arrays.stream(bpw.getViews()).anyMatch(clazz -> clazz.isAssignableFrom(provider.getActiveView()));
118+
}).toArray(BeanPropertyWriter[] ::new);
119+
} else {
120+
props = _props;
121+
}
122+
123+
for (BeanPropertyWriter prop : props) {
114124
try {
115125
if (prop.getAnnotation(EmbeddedResource.class) != null) {
116126
Object object = prop.get(bean);
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
package io.openapitoools.jackson.dataformat.hal.deser;
2+
3+
import com.fasterxml.jackson.annotation.JsonView;
4+
import com.fasterxml.jackson.databind.MapperFeature;
5+
import com.fasterxml.jackson.databind.ObjectMapper;
6+
import io.openapitools.jackson.dataformat.hal.HALLink;
7+
import io.openapitools.jackson.dataformat.hal.HALMapper;
8+
import io.openapitools.jackson.dataformat.hal.annotation.EmbeddedResource;
9+
import io.openapitools.jackson.dataformat.hal.annotation.Link;
10+
import io.openapitools.jackson.dataformat.hal.annotation.Resource;
11+
import org.junit.jupiter.api.Test;
12+
13+
import java.io.StringReader;
14+
import java.net.URI;
15+
16+
import static org.junit.jupiter.api.Assertions.*;
17+
18+
19+
public class HALBeanDeserializerJsonViewIT {
20+
static final String HAL_DOC_VIEW = "{" +
21+
"\"_links\":{" +
22+
"\"linkWithView1\":{" +
23+
"\"href\":\"/link/with/view/1\"," +
24+
"\"templated\":false" +
25+
"}}," +
26+
"\"_embedded\":{" +
27+
"\"childWithView1\":{" +
28+
"\"_links\":" +
29+
"{\"self\":" +
30+
"{\"href\":\"/top/1/child/childWithView1\"" +
31+
"}}," +
32+
"\"id\":\"childWithView1\"" +
33+
"}}," +
34+
"\"stateWithView1\":\"stateWithView1\"" +
35+
"}";
36+
37+
static final String HAL_DOC_INCLUSIVE_VIEW = "{\"_links\":{" +
38+
"\"linkWithView1\":{" +
39+
"\"href\":\"/link/with/view/1\"," +
40+
"\"templated\":false" +
41+
"}," +
42+
"\"linkWithoutView\":{" +
43+
"\"href\":\"/link/without/view\"," +
44+
"\"templated\":false" +
45+
"}}," +
46+
"\"_embedded\":{" +
47+
"\"childWithView1\":{" +
48+
"\"_links\":{" +
49+
"\"self\":{" +
50+
"\"href\":\"/top/1/child/childWithView1\"" +
51+
"}}," +
52+
"\"id\":\"childWithView1\"" +
53+
"}," +
54+
"\"childWithoutView\":{" +
55+
"\"_links\":{" +
56+
"\"self\":{" +
57+
"\"href\":\"/top/1/child/childWithoutView\"" +
58+
"}}," +
59+
"\"id\":\"childWithoutView\"" +
60+
"}}," +
61+
"\"stateWithoutView\":\"stateWithoutView\"," +
62+
"\"stateWithView1\":\"stateWithView1\"" +
63+
"}";
64+
65+
static final String HAL_DOC_NO_VIEW = "{\"_links\":{" +
66+
"\"linkWithView1\":{" +
67+
"\"href\":\"/link/with/view/1\"," +
68+
"\"templated\":false" +
69+
"}," +
70+
"\"linkWithView2\":{" +
71+
"\"href\":\"/link/with/view/2\",\"templated\":false" +
72+
"}," +
73+
"\"linkWithoutView\":{" +
74+
"\"href\":\"/link/without/view\"," +
75+
"\"templated\":false" +
76+
"}}," +
77+
"\"_embedded\":{" +
78+
"\"childWithView1\":{" +
79+
"\"_links\":{" +
80+
"\"self\":{" +
81+
"\"href\":\"/top/1/child/childWithView1\"" +
82+
"}}," +
83+
"\"id\":\"childWithView1\"" +
84+
"}," +
85+
"\"childWithView2\":{" +
86+
"\"_links\":{" +
87+
"\"self\":{" +
88+
"\"href\":\"/top/1/child/childWithView2\"" +
89+
"}}," +
90+
"\"id\":\"childWithView2\"" +
91+
"}," +
92+
"\"childWithoutView\":{" +
93+
"\"_links\":{" +
94+
"\"self\":{" +
95+
"\"href\":\"/top/1/child/childWithoutView\"" +
96+
"}}," +
97+
"\"id\":\"childWithoutView\"" +
98+
"}}," +
99+
"\"stateWithoutView\":\"stateWithoutView\"," +
100+
"\"stateWithView1\":\"stateWithView1\"" +
101+
",\"stateWithView2\":\"stateWithView2\"" +
102+
"}";
103+
104+
ObjectMapper om = new HALMapper();
105+
106+
@Test
107+
public void testDeserializationOfView() throws Exception {
108+
om.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false);
109+
TopResource tr = om.readerWithView(ResourceView1.class).readValue(new StringReader(HAL_DOC_VIEW), TopResource.class);
110+
111+
assertNull(tr.childWithoutView);
112+
assertNull(tr.linkWithoutView);
113+
assertNull(tr.stateWithoutView);
114+
115+
assertNotNull(tr.childWithView1);
116+
assertNotNull(tr.linkWithView1);
117+
assertNotNull(tr.stateWithView1);
118+
119+
assertNull(tr.childWithView2);
120+
assertNull(tr.linkWithView2);
121+
assertNull(tr.stateWithView2);
122+
123+
}
124+
125+
@Test
126+
public void testDeserializationOfViewWithInclusion() throws Exception {
127+
om.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, true);
128+
TopResource tr = om.readerWithView(ResourceView1.class).readValue(new StringReader(HAL_DOC_INCLUSIVE_VIEW), TopResource.class);
129+
130+
assertNotNull(tr.childWithoutView);
131+
assertNotNull(tr.linkWithoutView);
132+
assertNotNull(tr.stateWithoutView);
133+
134+
assertNotNull(tr.childWithView1);
135+
assertNotNull(tr.linkWithView1);
136+
assertNotNull(tr.stateWithView1);
137+
138+
assertNull(tr.childWithView2);
139+
assertNull(tr.linkWithView2);
140+
assertNull(tr.stateWithView2);
141+
}
142+
143+
@Test
144+
public void testDeserializationOfNoView() throws Exception {
145+
TopResource tr = om.readValue(new StringReader(HAL_DOC_NO_VIEW), TopResource.class);
146+
147+
assertNotNull(tr.childWithoutView);
148+
assertNotNull(tr.linkWithoutView);
149+
assertNotNull(tr.stateWithoutView);
150+
151+
assertNotNull(tr.childWithView1);
152+
assertNotNull(tr.linkWithView1);
153+
assertNotNull(tr.stateWithView1);
154+
155+
assertNotNull(tr.childWithView2);
156+
assertNotNull(tr.linkWithView2);
157+
assertNotNull(tr.stateWithView2);
158+
}
159+
160+
@Resource
161+
public static class TopResource {
162+
163+
// No View
164+
public String stateWithoutView;
165+
166+
@Link
167+
public HALLink linkWithoutView;
168+
169+
@EmbeddedResource("childWithoutView")
170+
public ChildResource childWithoutView;
171+
172+
// Resource View 1
173+
@JsonView(HALBeanDeserializerJsonViewIT.ResourceView1.class)
174+
public String stateWithView1;
175+
176+
@Link("linkWithView1")
177+
@JsonView(HALBeanDeserializerJsonViewIT.ResourceView1.class)
178+
public HALLink linkWithView1;
179+
180+
@EmbeddedResource("childWithView1")
181+
@JsonView(HALBeanDeserializerJsonViewIT.ResourceView1.class)
182+
public ChildResource childWithView1;
183+
184+
// Resource View 2
185+
@JsonView(HALBeanDeserializerJsonViewIT.ResourceView2.class)
186+
public String stateWithView2;
187+
188+
@Link("linkWithView2")
189+
@JsonView(HALBeanDeserializerJsonViewIT.ResourceView2.class)
190+
public HALLink linkWithView2;
191+
192+
@EmbeddedResource("childWithView2")
193+
@JsonView(HALBeanDeserializerJsonViewIT.ResourceView2.class)
194+
public ChildResource childWithView2;
195+
}
196+
197+
@Resource
198+
@JsonView({
199+
HALBeanDeserializerJsonViewIT.ResourceView1.class,
200+
HALBeanDeserializerJsonViewIT.ResourceView2.class
201+
})
202+
public static class ChildResource {
203+
204+
public String id;
205+
206+
@Link
207+
public HALLink self;
208+
}
209+
210+
public interface ResourceView1 {
211+
212+
}
213+
214+
public interface ResourceView2 {
215+
216+
}
217+
}

0 commit comments

Comments
 (0)