We can use those classes to create our own CSV MessageBodyWritter as shown below:
package csv; import com.fasterxml.jackson.dataformat.csv.CsvMapper; import com.fasterxml.jackson.dataformat.csv.CsvSchema; 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.MessageBodyWriter; import javax.ws.rs.ext.Provider; import java.io.IOException; import java.io.OutputStream; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.util.List; @Provider @Produces("text/csv") public class CSVMessageBodyWritter implements MessageBodyWriterTo use our MessageBodyWriter, it must be registered. This can achieved in several ways, depending on your JAX-RS implementation. Normally Jersey and other JAX-RS implementations are configured to scan packages and look for resources. In such cases classed marked with @Provider will be registered automatically. In other cases, the registration will have to be done manually. For example in Dropwizard, you have to manually register the Writer at startup:{ @Override public boolean isWriteable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { boolean ret=List.class.isAssignableFrom(type); return ret; } @Override public long getSize(List data, Class aClass, Type type, Annotation[] annotations, MediaType mediaType) { return 0; } @Override public void writeTo(List data, Class aClass, Type type, Annotation[] annotations, MediaType mediaType, MultivaluedMap
multivaluedMap, OutputStream outputStream) throws IOException, WebApplicationException { if (data!=null && data.size()>0) { CsvMapper mapper = new CsvMapper(); Object o=data.get(0); CsvSchema schema = mapper.schemaFor(o.getClass()).withHeader(); mapper.writer(schema).writeValue(outputStream,data); } } }
@Override public void run(MyConfiguration configuration, Environment environment) { environment.jersey().register(new CSVMessageBodyWritter()); }Once registered, it becomes trivial to have a web service that outputs CSV. It's just a matter of annotating your webservice with the same media type as the MessageBodyWritter: @Produces("text/csv").
import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import java.util.List; @Path("/status") public class StatusResource { @GET @Produces("text/csv") public List<Data> getData() { List<Data> data= service.getStatus(); return data; } }Our data class is just a normal POJO:
public class Data { private String date; private Integer minimum; private Integer maximum; private Integer average; public Data() { } //Getters and setters as needed }The output will look like this:
average,date,maximum,minimum 90,3/1856,125,0 60,2/1856,115,16 60,4/1856,115,16This is a very simple implementation, but should be a good starting point. It's worth nothing that CSV is inherently limited, and can't easily represent hierarchical object graphs. Therefore you might need flatten your data before exporting to CSV. If you need to ingest a CSV in a webservice, you can follow a similar approach to create a MessageBodyReader that will create an object from a CSV stream.
No comments:
Post a Comment