Skip to content

Commit

Permalink
Add ObjectMapper Module for Id de-/serialization
Browse files Browse the repository at this point in the history
  • Loading branch information
marecabo committed Oct 12, 2023
1 parent 6eed8f1 commit d5ee1ec
Show file tree
Hide file tree
Showing 4 changed files with 361 additions and 3 deletions.
6 changes: 3 additions & 3 deletions matsim/src/main/java/org/matsim/api/core/v01/Id.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,11 @@
/**
* Represents a unique identifier.
*
* Note that Ids should not contain any whitespace characters (spaces, tabs, newlines, ...),
* Note that Ids should not contain any whitespace characters (spaces, tabs,
* newlines, ...),
* as this may lead to problems when Ids are written to file and read back in.
*
* @author mrieser / Senozon AG
* @author mrieser / Senozon AG
*/
public abstract class Id<T> implements Comparable<Id<T>> {

Expand Down Expand Up @@ -145,7 +146,6 @@ public boolean equals(Object obj) {
// all other objects have to be different by definition, as long as the cache is correctly implemented
}


/**
* The default implementation to be used for Ids.
* Have this as a separate class instead of integrated into the Id class
Expand Down
28 changes: 28 additions & 0 deletions matsim/src/main/java/org/matsim/api/core/v01/IdAnnotations.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.KeyDeserializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
Expand Down Expand Up @@ -82,6 +83,15 @@ public Id<Person> deserialize(JsonParser jp, DeserializationContext ctxt) throws

}

static class PersonIdKeyDeserializer extends KeyDeserializer {

@Override
public Object deserializeKey(String key, DeserializationContext ctxt) throws IOException {
return Id.createPersonId(key);
}

}

}

@Retention(RetentionPolicy.RUNTIME)
Expand Down Expand Up @@ -125,6 +135,15 @@ public Id<Link> deserialize(JsonParser jp, DeserializationContext ctxt) throws I

}

static class LinkIdKeyDeserializer extends KeyDeserializer {

@Override
public Object deserializeKey(String key, DeserializationContext ctxt) throws IOException {
return Id.createLinkId(key);
}

}

}

@Retention(RetentionPolicy.RUNTIME)
Expand Down Expand Up @@ -168,6 +187,15 @@ public Id<Node> deserialize(JsonParser jp, DeserializationContext ctxt) throws I

}

static class NodeIdKeyDeserializer extends KeyDeserializer {

@Override
public Object deserializeKey(String key, DeserializationContext ctxt) throws IOException {
return Id.createNodeId(key);
}

}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
package org.matsim.api.core.v01;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.tuple.Triple;
import org.matsim.api.core.v01.IdAnnotations.JsonLinkId;
import org.matsim.api.core.v01.IdAnnotations.JsonNodeId;
import org.matsim.api.core.v01.IdAnnotations.JsonPersonId;
import org.matsim.api.core.v01.network.Link;
import org.matsim.api.core.v01.network.Node;
import org.matsim.api.core.v01.population.Person;
import org.matsim.core.utils.collections.Tuple;

import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.DeserializationConfig;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.KeyDeserializer;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.deser.Deserializers;
import com.fasterxml.jackson.databind.deser.KeyDeserializers;
import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
import com.fasterxml.jackson.databind.ser.Serializers;
import com.fasterxml.jackson.databind.type.ArrayType;
import com.fasterxml.jackson.databind.type.CollectionLikeType;
import com.fasterxml.jackson.databind.type.CollectionType;
import com.fasterxml.jackson.databind.type.MapLikeType;
import com.fasterxml.jackson.databind.type.MapType;
import com.fasterxml.jackson.databind.type.ReferenceType;

/**
* Use as follows with your {@link ObjectMapper} instance:
*
* {@code objectMapper.registerModule(IdDeSerializationModule.getInstance());}
*/
public class IdDeSerializationModule extends Module {

private static final String NAME = IdDeSerializationModule.class.getSimpleName();
private static final Version VERSION = new Version(0, 1, 0, null, "org.matsim", "api.core.v01");
private static final Map<Class<?>, Triple<JsonSerializer<?>, JsonDeserializer<?>, KeyDeserializer>> DE_SERIALIZER_MAP;
static {
Map<Class<?>, Triple<JsonSerializer<?>, JsonDeserializer<?>, KeyDeserializer>> m = new HashMap<>();
m.put(Person.class, Triple.of(
new JsonPersonId.PersonIdSerializer(),
new JsonPersonId.PersonIdDeserializer(),
new JsonPersonId.PersonIdKeyDeserializer()));
m.put(Node.class, Triple.of(
new JsonNodeId.NodeIdSerializer(),
new JsonNodeId.NodeIdDeserializer(),
new JsonNodeId.NodeIdKeyDeserializer()));
m.put(Link.class, Triple.of(
new JsonLinkId.LinkIdSerializer(),
new JsonLinkId.LinkIdDeserializer(),
new JsonLinkId.LinkIdKeyDeserializer()));
// Add your own classes below here
DE_SERIALIZER_MAP = Collections.unmodifiableMap(m);
}

private static Module instance = null;

private IdDeSerializationModule() {
// nothing to do here
}

public static Module getInstance() {
if (instance == null) {
instance = new IdDeSerializationModule();
}
return instance;
}

@Override
public String getModuleName() {
return NAME;
}

@Override
public Version version() {
return VERSION;
}

@Override
public void setupModule(SetupContext context) {
context.addSerializers(new IdSerializers());
context.addDeserializers(new IdDeserializers());
context.addKeyDeserializers(new IdKeyDeserializers());
}

private static final class IdDeserializers extends Deserializers.Base {

@Override
public JsonDeserializer<?> findEnumDeserializer(Class<?> type, DeserializationConfig config,
BeanDescription beanDesc) throws JsonMappingException {
return null;
}

@Override
public JsonDeserializer<?> findTreeNodeDeserializer(Class<? extends JsonNode> nodeType,
DeserializationConfig config, BeanDescription beanDesc) throws JsonMappingException {
return null;
}

@Override
public JsonDeserializer<?> findBeanDeserializer(JavaType type, DeserializationConfig config,
BeanDescription beanDesc) throws JsonMappingException {
if (type.getRawClass().equals(Id.class) && type.containedTypeCount() == 1) {
return DE_SERIALIZER_MAP.get(type.containedType(0).getRawClass()).getMiddle();
}
return null;
}

@Override
public JsonDeserializer<?> findReferenceDeserializer(ReferenceType refType,
DeserializationConfig config, BeanDescription beanDesc,
TypeDeserializer contentTypeDeserializer, JsonDeserializer<?> contentDeserializer)
throws JsonMappingException {
return null;
}

@Override
public JsonDeserializer<?> findArrayDeserializer(ArrayType type, DeserializationConfig config,
BeanDescription beanDesc, TypeDeserializer elementTypeDeserializer,
JsonDeserializer<?> elementDeserializer) throws JsonMappingException {
return null;
}

@Override
public JsonDeserializer<?> findCollectionDeserializer(CollectionType type,
DeserializationConfig config, BeanDescription beanDesc,
TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)
throws JsonMappingException {
return null;
}

@Override
public JsonDeserializer<?> findCollectionLikeDeserializer(CollectionLikeType type,
DeserializationConfig config, BeanDescription beanDesc,
TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)
throws JsonMappingException {
return null;
}

@Override
public JsonDeserializer<?> findMapDeserializer(MapType type, DeserializationConfig config,
BeanDescription beanDesc, KeyDeserializer keyDeserializer,
TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)
throws JsonMappingException {
return null;
}

@Override
public JsonDeserializer<?> findMapLikeDeserializer(MapLikeType type, DeserializationConfig config,
BeanDescription beanDesc, KeyDeserializer keyDeserializer,
TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)
throws JsonMappingException {
return null;
}

}

private static final class IdKeyDeserializers implements KeyDeserializers {

@Override
public KeyDeserializer findKeyDeserializer(JavaType type, DeserializationConfig config,
BeanDescription beanDesc) throws JsonMappingException {
if (type.getRawClass().equals(Id.class) && type.containedTypeCount() == 1) {
return DE_SERIALIZER_MAP.get(type.containedType(0).getRawClass()).getRight();
}
return null;
}

}

private static final class IdSerializers implements Serializers {

@Override
public JsonSerializer<?> findSerializer(SerializationConfig config, JavaType type,
BeanDescription beanDesc) {
if (type.getRawClass().equals(Id.class) && type.containedTypeCount() == 1) {
return DE_SERIALIZER_MAP.get(type.containedType(0).getRawClass()).getLeft();
}
return null;
}

@Override
public JsonSerializer<?> findReferenceSerializer(SerializationConfig config, ReferenceType type,
BeanDescription beanDesc, TypeSerializer contentTypeSerializer,
JsonSerializer<Object> contentValueSerializer) {
return null;
}

@Override
public JsonSerializer<?> findArraySerializer(SerializationConfig config, ArrayType type,
BeanDescription beanDesc, TypeSerializer elementTypeSerializer,
JsonSerializer<Object> elementValueSerializer) {
return null;
}

@Override
public JsonSerializer<?> findCollectionSerializer(SerializationConfig config, CollectionType type,
BeanDescription beanDesc, TypeSerializer elementTypeSerializer,
JsonSerializer<Object> elementValueSerializer) {
return null;
}

@Override
public JsonSerializer<?> findCollectionLikeSerializer(SerializationConfig config,
CollectionLikeType type, BeanDescription beanDesc, TypeSerializer elementTypeSerializer,
JsonSerializer<Object> elementValueSerializer) {
return null;
}

@Override
public JsonSerializer<?> findMapSerializer(SerializationConfig config, MapType type,
BeanDescription beanDesc, JsonSerializer<Object> keySerializer,
TypeSerializer elementTypeSerializer, JsonSerializer<Object> elementValueSerializer) {
return null;
}

@Override
public JsonSerializer<?> findMapLikeSerializer(SerializationConfig config, MapLikeType type,
BeanDescription beanDesc, JsonSerializer<Object> keySerializer,
TypeSerializer elementTypeSerializer, JsonSerializer<Object> elementValueSerializer) {
return null;
}
}
}
Loading

0 comments on commit d5ee1ec

Please sign in to comment.