-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #15 from camptocamp/feature/simple_json
Add simple JSON encoder
- Loading branch information
Showing
9 changed files
with
545 additions
and
89 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
102 changes: 102 additions & 0 deletions
102
...pendata/ogc/features/http/codec/json/SimpleJsonFeatureCollectionHttpMessageConverter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
package com.camptocamp.opendata.ogc.features.http.codec.json; | ||
|
||
import java.io.IOException; | ||
import java.io.OutputStream; | ||
import java.lang.reflect.Type; | ||
|
||
import org.springframework.http.HttpInputMessage; | ||
import org.springframework.http.HttpOutputMessage; | ||
import org.springframework.http.MediaType; | ||
import org.springframework.http.converter.AbstractGenericHttpMessageConverter; | ||
import org.springframework.http.converter.HttpMessageNotWritableException; | ||
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; | ||
import org.springframework.util.MimeType; | ||
|
||
import com.camptocamp.opendata.model.GeodataRecord; | ||
import com.camptocamp.opendata.ogc.features.http.codec.MimeTypes; | ||
import com.camptocamp.opendata.ogc.features.model.FeatureCollection; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
|
||
/** | ||
* Simpler, geometry-less, JSON encoder for {@link FeatureCollection} and | ||
* {@link GeodataRecord}. | ||
* | ||
* <p> | ||
* Sample output: | ||
* | ||
* <pre> | ||
* <code> | ||
* { | ||
* "numberMatched":16, | ||
* "numberReturned":2, | ||
* "records":[ | ||
* { | ||
* "@id":"1", | ||
* "city":" Trento", | ||
* "number":140, | ||
* "year":2002 | ||
* }, | ||
* ... | ||
* ], | ||
* "links":[ | ||
* { | ||
* "href":"http://localhost:8080/ogcapi/collections/locations/items?f=json&offset=0&limit=2", | ||
* "rel":"self", | ||
* "type":"application/json", | ||
* "title":"This document" | ||
* }, | ||
* ... | ||
* ] | ||
* } | ||
* </code> | ||
* </pre> | ||
* | ||
*/ | ||
public class SimpleJsonFeatureCollectionHttpMessageConverter | ||
extends AbstractGenericHttpMessageConverter<FeatureCollection> { | ||
|
||
private static final MimeType MIME_TYPE = MimeTypes.JSON.getMimeType(); | ||
private static final MediaType MEDIA_TYPE = new MediaType(MIME_TYPE); | ||
|
||
private ObjectMapper mapper; | ||
|
||
public SimpleJsonFeatureCollectionHttpMessageConverter() { | ||
super(MEDIA_TYPE); | ||
mapper = new ObjectMapper(); | ||
Jackson2ObjectMapperBuilder.json().configure(mapper); | ||
mapper.registerModule(new SimpleJsonModule()); | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
protected @Override boolean supports(Class<?> clazz) { | ||
return FeatureCollection.class.isAssignableFrom(clazz); | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
protected @Override MediaType getDefaultContentType(FeatureCollection message) { | ||
return MEDIA_TYPE; | ||
} | ||
|
||
protected @Override void writeInternal(FeatureCollection message, Type type, HttpOutputMessage outputMessage) | ||
throws IOException, HttpMessageNotWritableException { | ||
|
||
OutputStream body = outputMessage.getBody(); | ||
mapper.writeValue(body, message); | ||
body.flush(); | ||
} | ||
|
||
protected @Override FeatureCollection readInternal(Class<? extends FeatureCollection> clazz, | ||
HttpInputMessage inputMessage) { | ||
throw new UnsupportedOperationException(); | ||
} | ||
|
||
@Override | ||
public FeatureCollection read(Type type, Class<?> contextClass, HttpInputMessage inputMessage) { | ||
throw new UnsupportedOperationException(); | ||
} | ||
|
||
} |
135 changes: 135 additions & 0 deletions
135
.../src/main/java/com/camptocamp/opendata/ogc/features/http/codec/json/SimpleJsonModule.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
package com.camptocamp.opendata.ogc.features.http.codec.json; | ||
|
||
import java.io.IOException; | ||
import java.io.UncheckedIOException; | ||
import java.util.List; | ||
|
||
import com.camptocamp.opendata.model.GeodataRecord; | ||
import com.camptocamp.opendata.model.GeometryProperty; | ||
import com.camptocamp.opendata.model.SimpleProperty; | ||
import com.camptocamp.opendata.ogc.features.model.FeatureCollection; | ||
import com.fasterxml.jackson.core.JsonGenerator; | ||
import com.fasterxml.jackson.core.JsonToken; | ||
import com.fasterxml.jackson.core.Version; | ||
import com.fasterxml.jackson.core.type.WritableTypeId; | ||
import com.fasterxml.jackson.databind.SerializerProvider; | ||
import com.fasterxml.jackson.databind.jsontype.TypeSerializer; | ||
import com.fasterxml.jackson.databind.module.SimpleModule; | ||
import com.fasterxml.jackson.databind.ser.std.StdSerializer; | ||
|
||
@SuppressWarnings("serial") | ||
class SimpleJsonModule extends SimpleModule { | ||
|
||
private static final Version VERSION = new Version(1, 0, 0, null, null, null); | ||
|
||
public SimpleJsonModule() { | ||
super(SimpleJsonModule.class.getSimpleName(), VERSION); | ||
|
||
addSerializer(new FeatureCollectionSerializer()); | ||
addSerializer(new GeodataRecordSerializer()); | ||
} | ||
|
||
static class FeatureCollectionSerializer extends StdSerializer<FeatureCollection> { | ||
|
||
protected FeatureCollectionSerializer() { | ||
super(FeatureCollection.class); | ||
} | ||
|
||
@Override | ||
public void serializeWithType(FeatureCollection collection, JsonGenerator gen, SerializerProvider serializers, | ||
TypeSerializer typeSer) throws IOException { | ||
|
||
WritableTypeId typeIdDef = typeSer.writeTypePrefix(gen, typeSer.typeId(collection, JsonToken.START_OBJECT)); | ||
|
||
serializeContent(collection, gen); | ||
|
||
typeSer.writeTypeSuffix(gen, typeIdDef); | ||
} | ||
|
||
@Override | ||
public void serialize(FeatureCollection collection, JsonGenerator generator, SerializerProvider serializers) | ||
throws IOException { | ||
|
||
if (collection == null) { | ||
generator.writeNull(); | ||
return; | ||
} | ||
generator.writeStartObject(); | ||
serializeContent(collection, generator); | ||
generator.writeEndObject(); | ||
} | ||
|
||
private void serializeContent(FeatureCollection collection, JsonGenerator generator) throws IOException { | ||
generator.writeNumberField("numberMatched", collection.getNumberMatched()); | ||
generator.writeNumberField("numberReturned", collection.getNumberReturned()); | ||
|
||
generator.writeFieldName("records"); | ||
generator.writeStartArray(); | ||
collection.getFeatures().forEach(rec -> write(rec, generator)); | ||
generator.writeEndArray(); | ||
|
||
generator.writeFieldName("links"); | ||
generator.writeStartArray(); | ||
collection.getLinks().forEach(link -> write(link, generator)); | ||
generator.writeEndArray(); | ||
} | ||
|
||
private void write(Object obj, JsonGenerator generator) { | ||
try { | ||
generator.writeObject(obj); | ||
} catch (IOException e) { | ||
throw new UncheckedIOException(e); | ||
} | ||
} | ||
|
||
} | ||
|
||
static class GeodataRecordSerializer extends StdSerializer<GeodataRecord> { | ||
|
||
public GeodataRecordSerializer() { | ||
super(GeodataRecord.class); | ||
} | ||
|
||
@Override | ||
public void serializeWithType(GeodataRecord rec, JsonGenerator gen, SerializerProvider serializers, | ||
TypeSerializer typeSer) throws IOException { | ||
|
||
WritableTypeId typeIdDef = typeSer.writeTypePrefix(gen, typeSer.typeId(rec, JsonToken.START_OBJECT)); | ||
|
||
serializeContent(rec, gen); | ||
|
||
typeSer.writeTypeSuffix(gen, typeIdDef); | ||
} | ||
|
||
@Override | ||
public void serialize(GeodataRecord rec, JsonGenerator generator, SerializerProvider serializers) | ||
throws IOException { | ||
|
||
if (rec == null) { | ||
generator.writeNull(); | ||
return; | ||
} | ||
generator.writeStartObject(); | ||
serializeContent(rec, generator); | ||
generator.writeEndObject(); | ||
} | ||
|
||
private void serializeContent(GeodataRecord rec, JsonGenerator generator) throws IOException { | ||
if (null != rec.getId()) { | ||
generator.writeStringField("@id", rec.getId()); | ||
} | ||
writeProperties(generator, rec.getProperties()); | ||
} | ||
|
||
private void writeProperties(JsonGenerator generator, List<? extends SimpleProperty<?>> properties) | ||
throws IOException { | ||
for (SimpleProperty<?> p : properties) { | ||
if (!(p instanceof GeometryProperty)) { | ||
generator.writeObjectField(p.getName(), p.getValue()); | ||
} | ||
} | ||
} | ||
|
||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.