Skip to content

Commit

Permalink
Merge pull request #30 from kozusznik/preparingForMergeRequest
Browse files Browse the repository at this point in the history
Enable interval serialization
  • Loading branch information
ctrueden authored Jul 9, 2020
2 parents 28e031a + 967f973 commit d69f215
Show file tree
Hide file tree
Showing 8 changed files with 196 additions and 12 deletions.
8 changes: 3 additions & 5 deletions src/main/java/net/imagej/server/ImageJServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,22 +49,20 @@
*
* @author Leon Yang
*/
public class ImageJServer extends
Application<ImageJServerConfiguration>
{
public class ImageJServer extends Application<ImageJServerConfiguration> {

private final Context ctx;

private final ObjectService objectService;

private final JsonService jsonService;

private Environment env;

public ImageJServer(final Context ctx) {
this.ctx = ctx;
objectService = new DefaultObjectService();
jsonService = new DefaultJsonService(objectService);
jsonService = new DefaultJsonService(ctx, objectService);
}

@Override
Expand Down
29 changes: 29 additions & 0 deletions src/main/java/net/imagej/server/json/JsonSerializerAdapter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package net.imagej.server.json;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;

import java.io.IOException;

class JsonSerializerAdapter<T> extends StdSerializer<T> {

private SciJavaJsonSerializer<T> serializedDelegate;

public JsonSerializerAdapter(
SciJavaJsonSerializer<T> serializedDelegate)
{
super(serializedDelegate.handleType());
this.serializedDelegate = serializedDelegate;
}


@Override
public void serialize(T value, JsonGenerator gen,
SerializerProvider provider) throws IOException
{
serializedDelegate.serialize(value, gen, provider);
}


}
32 changes: 32 additions & 0 deletions src/main/java/net/imagej/server/json/SciJavaJsonSerializer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@

package net.imagej.server.json;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;

import java.io.IOException;

import org.scijava.plugin.SciJavaPlugin;

public interface SciJavaJsonSerializer<T> extends SciJavaPlugin

{

void serialize(T value, JsonGenerator gen,
SerializerProvider serializers)
throws IOException;

Class<T> handleType();

default boolean isSupportedBy(Class<?> desiredClass) {
return handleType().isAssignableFrom(desiredClass);
}

default public void register(ObjectMapper mapper) {
SimpleModule mod = new SimpleModule();
mod.addSerializer(new JsonSerializerAdapter<>(this));
mapper.registerModule(mod);
}
}
38 changes: 33 additions & 5 deletions src/main/java/net/imagej/server/services/DefaultJsonService.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,15 @@

import java.io.IOException;
import java.util.Arrays;
import java.util.List;

import net.imagej.server.json.SciJavaJsonSerializer;
import net.imagej.server.mixins.Mixins;
import net.imglib2.EuclideanSpace;

import org.scijava.Context;
import org.scijava.plugin.PluginService;

/**
* Service that handle customized JSON serialization and deserialization.
*
Expand All @@ -73,13 +78,16 @@ public class DefaultJsonService implements JsonService {
*/
private final UntypedObjectDeserializer idToObjDeserializer;

private final List<?> jsonSerializers;

/**
* Constructs and initializes a JsonService with an {@link ObjectService}.
*
* @param objectService
*/
public DefaultJsonService(final ObjectService objectService) {

public DefaultJsonService(final Context ctx,
final ObjectService objectService)
{
idToObjDeserializer = new UntypedObjectDeserializer(null, null) {

@Override
Expand All @@ -101,7 +109,7 @@ public Object deserialize(JsonParser p, DeserializationContext ctxt)

final JsonSerializer<Object> objToIdSerializer =
new JsonSerializer<Object>()
{
{

@Override
public void serialize(Object value, JsonGenerator gen,
Expand All @@ -120,20 +128,36 @@ public void serialize(Object value, JsonGenerator gen,
public JsonSerializer<?> modifySerializer(SerializationConfig config,
BeanDescription beanDesc, JsonSerializer<?> serializer)
{
if (Mixins.support(beanDesc.getBeanClass())) return serializer;
final Class<?> desiredClass = beanDesc.getBeanClass();

// If the serialized class is supported by mixins, let's go for one
if (Mixins.support(desiredClass)) return serializer;

// If the serialized class is supported thanks to a modification to
// ObjectMapper, let's do it that way
if (jsonSerializers.stream().map(obj -> (SciJavaJsonSerializer<?>) obj)
.anyMatch(e -> e.isSupportedBy(
desiredClass))) return serializer;

// If the serialized class is unknown (i.e. serialized using the general
// BeanSerializer) or should not be serialized (i.e. complicated class
// implemented interfaces such as Iterable), would be serialized as an
// ID.
if (serializer instanceof BeanSerializer) return objToIdSerializer;
if (notSerialized(beanDesc.getBeanClass())) return objToIdSerializer;
if (notSerialized(desiredClass)) return objToIdSerializer;

return serializer;

}
});
objToIdMapper = new ObjectMapper();
objToIdMapper.registerModule(objToIdModule);

jsonSerializers = ctx.getService(PluginService.class).createInstancesOfType(
SciJavaJsonSerializer.class);

registerSerializers();

// register Jackson MixIns to obtain better json output format for some
// specific types
Mixins.registerMixIns(objToIdMapper);
Expand All @@ -156,4 +180,8 @@ public boolean notSerialized(final Class<?> target) {
.isAssignableFrom(target));
}

private void registerSerializers() {
jsonSerializers.stream().map(obj -> (SciJavaJsonSerializer<?>) obj).forEach(
serializer -> serializer.register(objToIdMapper));
}
}
2 changes: 1 addition & 1 deletion src/test/java/net/imagej/server/AbstractResourceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public abstract class AbstractResourceTest {
protected static final ObjectService objectService =
new DefaultObjectService();

protected static final JsonService jsonService = new DefaultJsonService(
protected static final JsonService jsonService = new DefaultJsonService(ctx,
objectService);

protected static final ObjectMapper objectMapper = new ObjectMapper();
Expand Down
4 changes: 3 additions & 1 deletion src/test/java/net/imagej/server/DefaultJsonServiceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@

import org.junit.Before;
import org.junit.Test;
import org.scijava.Context;

/**
* Test deserialization and serialization using DefaultJsonService.
Expand All @@ -66,12 +67,13 @@ public class DefaultJsonServiceTest {
private ObjectMapper modifiedMapper;
private ListObjectService objectService;
private DefaultJsonService jsonService;
protected static final Context ctx = new Context();

@Before
public void setup() {
modifiedMapper = Jackson.newObjectMapper();
objectService = new ListObjectService();
jsonService = new DefaultJsonService(objectService);
jsonService = new DefaultJsonService(ctx, objectService);
jsonService.addDeserializerTo(modifiedMapper);
}

Expand Down
89 changes: 89 additions & 0 deletions src/test/java/net/imagej/server/SciJavaJsonSerializerTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@

package net.imagej.server;

import static io.dropwizard.testing.FixtureHelpers.fixture;
import static org.junit.Assert.assertEquals;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;

import io.dropwizard.jackson.Jackson;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import net.imagej.server.json.SciJavaJsonSerializer;
import net.imagej.server.services.DefaultJsonService;
import net.imagej.server.services.DefaultObjectService;
import net.imglib2.FinalInterval;
import net.imglib2.Interval;

import org.junit.Test;
import org.scijava.Context;
import org.scijava.plugin.Plugin;

public class SciJavaJsonSerializerTest {

@Test
public void serializeIntervalUsingSciJavaJsonSerializer() throws Exception {

final ObjectMapper mapper = Jackson.newObjectMapper();
final DefaultObjectService objectService = new DefaultObjectService();
final DefaultJsonService jsonService = new DefaultJsonService(new Context(),
objectService);
jsonService.addDeserializerTo(mapper);

final Interval testInterval = new FinalInterval(new long[] { 0, 1 },
new long[] { 8, 9 });
final Map<String, Object> outputs = new HashMap<>();
outputs.put("testInterval", testInterval);

final String parsed = jsonService.parseObject(outputs);

final String expected = mapper.writeValueAsString(mapper.readValue(fixture(
"fixtures/outputs/finalIntervalType.json"), Map.class));

assertEquals(expected, parsed);

}

@Plugin(type = SciJavaJsonSerializer.class)
public static class ExampleIntervalJsonSerializer implements
SciJavaJsonSerializer<Interval>
{

@Override
public boolean isSupportedBy(Class<?> desiredClass) {
return desiredClass.equals(FinalInterval.class);
}

@Override
public void serialize(Interval interval, JsonGenerator gen,
SerializerProvider serializers) throws IOException
{

gen.writeStartObject();
gen.writeArrayFieldStart("min");
for (int i = 0; i < interval.numDimensions(); i++) {
gen.writeNumber(interval.min(i));
}
gen.writeEndArray();
gen.writeArrayFieldStart("max");
for (int i = 0; i < interval.numDimensions(); i++) {
gen.writeNumber(interval.max(i));
}
gen.writeEndArray();
gen.writeEndObject();

}

@Override
public Class<Interval> handleType() {
return Interval.class;
}

}

}
6 changes: 6 additions & 0 deletions src/test/resources/fixtures/outputs/finalIntervalType.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"testInterval": {
"min": [0, 1],
"max": [8, 9]
}
}

0 comments on commit d69f215

Please sign in to comment.