问题
Well, anybody can say this question is already asked and answered. Never mind I also found them.
- JAX-RS: How to automatically serialize a collection when returning a Response object?
- Using Java-generics template type in RESTful Response object via GenericEntity<List<T>>
I'm not confused with the way of responding with an List<T>
but just not convinced about the portability.
Let's say I have a nicely annotated entity looks like this.
@XmlRootElement
public class Stock {
@XmlAttribute
private Long id;
}
List<Stock>
When do like this,
@GET
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public List<Stock> readStocks() {
final List<Stock> list = getStocks();
return list;
}
As far as know, GlassFish and WileFly works.
<stocks> <!-- automatic plural? -->
<stock xmlns="http://...">
</stock>\
<stock xmlns="http://...">
</stock>
</stocks>
<collection> <!-- fixed? -->
<stock xmlns="http://...">
</stock>\
<stock xmlns="http://...">
</stock>
</collection>
and JSON, (it could be vary by providers, i think)
[
{
"id": 1
},
{
"id": 2
}
]
GenericEntity<List<Stock>>
Sometime I see a problem when the container couldn't find a MessageBodyWriter
. So that I do like this.
@GET
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public GenericEntity<List<T>> readStocks() {
return new GenericEntity<List<Stock>>(getStocks()) {};
}
or
@GET
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Response readStocks() {
return Response.ok(new GenericEntity<List<Stock>>(getStocks()) {}).build();
}
WrapperClass
@XmlRootElement
public class Stocks {
@XmlElement
private List<Stock> stock;
}
@GET
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Stocks readStocks() {
final Stocks entity; ///
return Response.ok(entity).build();
}
According to 4.2.4 Standard Entity Providers (JSR-339), List
is not on the list of mandatory prepackaged MessageBody(Reader|Writer)
.
Is List<T>
standardized? or Which way is the most portable one?
回答1:
It's not really a problem with List
. The MBWs for both JSON and XML generally always return true for isWritable
. That's how they are able to handle all types you throw are them. What is has to do with is type erasure. The purpose of the GenericEntity
is that is caches the generic type parameter, which allows the MBW to know what type to marshal as.
Note that GenericEntity
is generally use when returning Response
. Imagine this case
public Response get() {
List<Somthing> l = service.get();
return Response.ok(l).build();
}
Because of type erasure, there's just no way for MBW to know the type, by the time the entity gets to it. With some provider it doesn't matter. For example with Jackson it generally doesn't need to know the type, as it just introspects properties for serialization. But with MOXy/JAXB, it inherently needs to know the class. That's where the GenericEntity comes to play.
Normally type erasure removes generic type information such that a
Response
instance that contains, e.g., an entity of typeList<String>
appears to contain a rawList<?>
at runtime. When the generic type is required to select a suitableMessageBodyWriter
, this class may be used to wrap the entity and capture its generic type....
List<String> list = new ArrayList<String>(); GenericEntity<List<String>> entity = new GenericEntity<List<String>>(list) {}; Response response = Response.ok(entity).build();
来源:https://stackoverflow.com/questions/33190552/what-is-the-most-portable-or-standard-way-of-returning-a-list-as-a-response-in