/
GensonJsonConverter.java
141 lines (121 loc) · 5.55 KB
/
GensonJsonConverter.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package com.owlike.genson.ext.jaxrs;
import java.io.*;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Arrays;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.ext.Providers;
import com.owlike.genson.*;
import com.owlike.genson.annotation.WithBeanView;
import com.owlike.genson.ext.jaxb.JAXBBundle;
import com.owlike.genson.stream.JsonStreamException;
import com.owlike.genson.stream.ObjectReader;
import com.owlike.genson.stream.ObjectWriter;
@Provider
@Consumes({MediaType.APPLICATION_JSON, "text/json", "application/*+json"})
@Produces({MediaType.APPLICATION_JSON, "text/json", "application/*+json"})
public class GensonJsonConverter implements MessageBodyReader<Object>, MessageBodyWriter<Object> {
private final ContextResolver<GensonJaxRSFeature> _gensonResolver;
public GensonJsonConverter() {
this(new GensonJaxRSFeature());
}
public GensonJsonConverter(@javax.ws.rs.core.Context Providers providers) {
ContextResolver<GensonJaxRSFeature> gensonResolver = providers.getContextResolver(GensonJaxRSFeature.class, null);
if (gensonResolver == null) {
// This allows us to remain compatible with existing user code that would register a custom resolver.
ContextResolver<Genson> oldResolver = providers.getContextResolver(Genson.class, null);
if (oldResolver != null) {
gensonResolver = new GensonJaxRSFeature().use(oldResolver.getContext(Object.class));
}
}
if (gensonResolver == null)
_gensonResolver = new GensonJaxRSFeature();
else
_gensonResolver = gensonResolver;
}
public GensonJsonConverter(ContextResolver<GensonJaxRSFeature> gensonResolver) {
this._gensonResolver = gensonResolver;
}
private Genson getInstance(Class<?> type) {
Genson genson = _gensonResolver.getContext(type).genson();
if (genson == null)
throw new NullPointerException("Could not resolve a Genson instance for type " + type
+ " using ContextResolver " + _gensonResolver.getClass());
return genson;
}
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations,
MediaType mediaType) {
GensonJaxRSFeature feature = _gensonResolver.getContext(type);
return feature.isEnabled() && feature.isSerializable(type);
}
public void writeTo(Object t, Class<?> type, Type genericType, Annotation[] annotations,
MediaType mediaType, MultivaluedMap<String, Object> httpHeaders,
OutputStream entityStream) throws IOException, WebApplicationException {
Genson genson = getInstance(type);
String charset = mediaType.getParameters().get("charset");
if (charset == null) charset = "UTF-8";
if (!charset.equalsIgnoreCase("UTF-8")
&& !charset.equalsIgnoreCase("UTF-16BE") && !charset.equalsIgnoreCase("UTF-16LE")
&& !charset.equalsIgnoreCase("UTF-32BE") && !charset.equalsIgnoreCase("UTF-32LE"))
throw new UnsupportedEncodingException("JSON spec allows only UTF-8/16/32 encodings.");
ObjectWriter writer = genson.createWriter(new OutputStreamWriter(entityStream, charset));
try {
genson.serialize(t, rawIfNullGenericType(type, genericType), writer, createContext(annotations, genson));
writer.flush();
} catch (JsonBindingException e) {
throw new WebApplicationException(e);
} catch (JsonStreamException jse) {
throw new WebApplicationException(jse);
}
}
private Context createContext(Annotation[] annotations, Genson genson) {
WithBeanView viewAnno = find(WithBeanView.class, annotations);
Context context = null;
if (viewAnno != null)
context = new Context(genson, Arrays.asList(viewAnno.views()));
else
context = new Context(genson);
return context;
}
private <T extends Annotation> T find(Class<T> annotationClass, Annotation[] inAnnotations) {
if (inAnnotations != null) {
for (Annotation anno : inAnnotations)
if (annotationClass.isInstance(anno))
return annotationClass.cast(anno);
}
return null;
}
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations,
MediaType mediaType) {
GensonJaxRSFeature feature = _gensonResolver.getContext(type);
return feature.isEnabled() && feature.isDeserializable(type);
}
public Object readFrom(Class<Object> type, Type genericType, Annotation[] annotations,
MediaType mediaType, MultivaluedMap<String, String> httpHeaders,
InputStream entityStream) throws IOException, WebApplicationException {
try {
Genson genson = getInstance(type);
ObjectReader reader = genson.createReader(entityStream);
return genson.deserialize(GenericType.of(rawIfNullGenericType(type, genericType)), reader, createContext(annotations, genson));
} catch (JsonBindingException e) {
throw new WebApplicationException(e);
} catch (JsonStreamException jse) {
throw new WebApplicationException(jse);
}
}
public long getSize(Object t, Class<?> type, Type genericType, Annotation[] annotations,
MediaType mediaType) {
return -1;
}
private Type rawIfNullGenericType(Class<?> rawType, Type genericType) {
return genericType != null ? genericType : rawType;
}
}