diff --git a/src/main/java/ch/psi/daq/queryrest/config/QueryRestConfig.java b/src/main/java/ch/psi/daq/queryrest/config/QueryRestConfig.java index 151b9be..3ef9163 100644 --- a/src/main/java/ch/psi/daq/queryrest/config/QueryRestConfig.java +++ b/src/main/java/ch/psi/daq/queryrest/config/QueryRestConfig.java @@ -41,6 +41,7 @@ import ch.psi.daq.query.model.QueryField; import ch.psi.daq.query.model.impl.AbstractQuery; import ch.psi.daq.queryrest.controller.validator.QueryValidator; import ch.psi.daq.queryrest.model.PropertyFilterMixin; +import ch.psi.daq.queryrest.response.JsonByteArraySerializer; import ch.psi.daq.queryrest.response.JsonStreamSerializer; import ch.psi.daq.queryrest.response.ResponseStreamWriter; @@ -75,16 +76,16 @@ public class QueryRestConfig extends WebMvcConfigurerAdapter { */ @Override public void configureMessageConverters(List> converters) { - final MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); - /** + final MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); + /** * This is necessary so that the message conversion uses the configured object mapper. * Otherwise, a separate object mapper is instantiated for Springs message conversion. */ - converter.setObjectMapper(objectMapper()); - converters.add(converter); - super.configureMessageConverters(converters); + converter.setObjectMapper(objectMapper()); + converters.add(converter); + super.configureMessageConverters(converters); } - + @Bean public ObjectMapper objectMapper() { ObjectMapper mapper = new ObjectMapper(); @@ -110,9 +111,14 @@ public class QueryRestConfig extends WebMvcConfigurerAdapter { module.addSerializer(new JsonStreamSerializer()); mapper.registerModule(module); + // by default, byte[] are written as String + module = new SimpleModule("byte[]", Version.unknownVersion()); + module.addSerializer(new JsonByteArraySerializer()); + mapper.registerModule(module); + return mapper; } - + @Bean public JsonFactory jsonFactory() { return new JsonFactory(); @@ -133,7 +139,7 @@ public class QueryRestConfig extends WebMvcConfigurerAdapter { String[] responseFields = StringUtils.commaDelimitedListToStringArray(env.getProperty(QUERYREST_DEFAULT_RESPONSE_FIELDS)); LOGGER.debug("Load '{}={}'", BEAN_NAME_DEFAULT_RESPONSE_FIELDS, Arrays.toString(responseFields)); - + // preserve order LinkedHashSet defaultResponseFields = new LinkedHashSet<>(responseFields.length); for (String field : responseFields) { @@ -152,7 +158,7 @@ public class QueryRestConfig extends WebMvcConfigurerAdapter { String[] responseAggregations = StringUtils.commaDelimitedListToStringArray(env.getProperty(QUERYREST_DEFAULT_RESPONSE_AGGREGATIONS)); LOGGER.debug("Load '{}={}'", BEAN_NAME_DEFAULT_RESPONSE_AGGREGATIONS, Arrays.toString(responseAggregations)); - + // preserve order LinkedHashSet defaultResponseAggregations = new LinkedHashSet<>(responseAggregations.length); for (String aggregation : responseAggregations) { @@ -166,7 +172,7 @@ public class QueryRestConfig extends WebMvcConfigurerAdapter { return defaultResponseAggregations; } - + @Bean public Validator queryValidator() { return new QueryValidator(); diff --git a/src/main/java/ch/psi/daq/queryrest/response/JsonByteArraySerializer.java b/src/main/java/ch/psi/daq/queryrest/response/JsonByteArraySerializer.java new file mode 100644 index 0000000..e01cea1 --- /dev/null +++ b/src/main/java/ch/psi/daq/queryrest/response/JsonByteArraySerializer.java @@ -0,0 +1,30 @@ +package ch.psi.daq.queryrest.response; + +import java.io.IOException; + +import com.fasterxml.jackson.core.JsonGenerationException; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; + +// see: http://stackoverflow.com/a/15037329 +public class JsonByteArraySerializer extends StdSerializer { + private static final long serialVersionUID = -5914688899857435263L; + + public JsonByteArraySerializer() { + super(byte[].class, true); + } + + @Override + public void serialize(byte[] bytes, JsonGenerator jgen, SerializerProvider provider) throws IOException, + JsonGenerationException { + jgen.writeStartArray(); + + for (byte b : bytes) { + // stackoverflow example used a mask -> ? + jgen.writeNumber(b); + } + + jgen.writeEndArray(); + } +} diff --git a/src/main/java/ch/psi/daq/queryrest/response/ResponseStreamWriter.java b/src/main/java/ch/psi/daq/queryrest/response/ResponseStreamWriter.java index 973ea78..e5c5483 100644 --- a/src/main/java/ch/psi/daq/queryrest/response/ResponseStreamWriter.java +++ b/src/main/java/ch/psi/daq/queryrest/response/ResponseStreamWriter.java @@ -12,6 +12,7 @@ import javax.servlet.ServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.http.MediaType; import com.fasterxml.jackson.core.JsonEncoding; import com.fasterxml.jackson.core.JsonFactory; @@ -100,6 +101,8 @@ public class ResponseStreamWriter { ObjectWriter writer) throws IOException { + response.setCharacterEncoding(JsonEncoding.UTF8.getJavaName()); + response.setContentType(MediaType.APPLICATION_JSON_VALUE); JsonGenerator generator = jsonFactory.createGenerator(response.getOutputStream(), JsonEncoding.UTF8); generator.writeStartArray(); stream diff --git a/src/main/resources/queryrest.properties b/src/main/resources/queryrest.properties index 1050546..762a6d3 100644 --- a/src/main/resources/queryrest.properties +++ b/src/main/resources/queryrest.properties @@ -3,5 +3,5 @@ server.port=8080 # defines the fields that are included in the response # if no fields have been specified by the user -queryrest.default.response.fields=channel,pulseId,globalMillis,globalNanos,value +queryrest.default.response.fields=channel,pulseId,globalMillis,globalNanos,iocMillis,iocNanos,value queryrest.default.response.aggregations=min,max,sum \ No newline at end of file