Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ compile("io.vavr:vavr-jackson:0.10.3")
### Registering module
Just register a new instance of <code>VavrModule</code>
```java
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new VavrModule());
ObjectMapper mapper = new ObjectMapper().rebuild().addModule(new VavrModule()).build();
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There might be a better way than using rebuild, but this was the quickest way without changing the code significantly. This strategy was employed throughout the PR.

```

### Serialization/deserialization
Expand Down
40 changes: 14 additions & 26 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<maven.central.publishing.version>0.8.0</maven.central.publishing.version>

<vavr.version>0.10.7</vavr.version>
<fasterxml.version>2.13.5</fasterxml.version>
<jackson.version>3.0.3</jackson.version>
<junit.jupiter.version>5.13.4</junit.jupiter.version>
<assertj.version>3.27.4</assertj.version>
<jaxb.version>2.3.1</jaxb.version>
Expand Down Expand Up @@ -48,9 +48,9 @@
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<groupId>tools.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${fasterxml.version}</version>
<version>${jackson.version}</version>
</dependency>

<!-- Test dependencies -->
Expand Down Expand Up @@ -90,45 +90,33 @@
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<groupId>tools.jackson.module</groupId>
<artifactId>jackson-module-jaxb-annotations</artifactId>
<version>${fasterxml.version}</version>
<version>${jackson.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<groupId>tools.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-csv</artifactId>
<version>${fasterxml.version}</version>
<version>${jackson.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<groupId>tools.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>${fasterxml.version}</version>
<version>${jackson.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<groupId>tools.jackson.datatype</groupId>
<artifactId>jackson-datatype-joda</artifactId>
<version>${fasterxml.version}</version>
<version>${jackson.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>${fasterxml.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
<version>${fasterxml.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-scala_2.11</artifactId>
<version>${fasterxml.version}</version>
<groupId>tools.jackson.module</groupId>
<artifactId>jackson-module-scala_2.12</artifactId>
<version>${jackson.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/io/vavr/jackson/datatype/VavrModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
*/
package io.vavr.jackson.datatype;

import com.fasterxml.jackson.databind.module.SimpleModule;
import tools.jackson.databind.module.SimpleModule;
import io.vavr.jackson.datatype.deserialize.VavrDeserializers;
import io.vavr.jackson.datatype.serialize.VavrSerializers;

Expand Down
14 changes: 7 additions & 7 deletions src/main/java/io/vavr/jackson/datatype/VavrTypeModifier.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@
*/
package io.vavr.jackson.datatype;

import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.type.CollectionLikeType;
import com.fasterxml.jackson.databind.type.MapLikeType;
import com.fasterxml.jackson.databind.type.ReferenceType;
import com.fasterxml.jackson.databind.type.TypeBindings;
import com.fasterxml.jackson.databind.type.TypeFactory;
import com.fasterxml.jackson.databind.type.TypeModifier;
import tools.jackson.databind.JavaType;
import tools.jackson.databind.type.CollectionLikeType;
import tools.jackson.databind.type.MapLikeType;
import tools.jackson.databind.type.ReferenceType;
import tools.jackson.databind.type.TypeBindings;
import tools.jackson.databind.type.TypeFactory;
import tools.jackson.databind.type.TypeModifier;
import io.vavr.Lazy;
import io.vavr.collection.CharSeq;
import io.vavr.collection.Map;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,37 +19,35 @@
*/
package io.vavr.jackson.datatype.deserialize;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
import tools.jackson.core.JsonToken;
import tools.jackson.databind.BeanProperty;
import tools.jackson.databind.DatabindException;
import tools.jackson.databind.DeserializationContext;
import tools.jackson.databind.JavaType;
import tools.jackson.databind.ValueDeserializer;
import tools.jackson.databind.jsontype.TypeDeserializer;
import io.vavr.collection.Traversable;
import tools.jackson.core.JsonParser;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import static com.fasterxml.jackson.core.JsonToken.END_ARRAY;
import static com.fasterxml.jackson.core.JsonToken.VALUE_NULL;
import static tools.jackson.core.JsonToken.END_ARRAY;
import static tools.jackson.core.JsonToken.VALUE_NULL;

abstract class ArrayDeserializer<T> extends ValueDeserializer<T> implements ContextualDeserializer {
abstract class ArrayDeserializer<T> extends VavrValueDeserializer<T> {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The local ValueDeserializer/ValueSerializer was renamed due to a naming conflict with Jackson 3's classes of the same names.


private static final long serialVersionUID = 1L;

protected final JavaType collectionType;
protected final JavaType elementType;
protected final TypeDeserializer elementTypeDeserializer;
protected final JsonDeserializer<?> elementDeserializer;
protected final ValueDeserializer<?> elementDeserializer;
protected final boolean deserializeNullAsEmptyCollection;

ArrayDeserializer(JavaType collectionType, int typeCount, JavaType elementType,
TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer,
TypeDeserializer elementTypeDeserializer, ValueDeserializer<?> elementDeserializer,
boolean deserializeNullAsEmptyCollection) {
super(collectionType, typeCount);
this.collectionType = collectionType;
Expand All @@ -59,7 +57,7 @@ abstract class ArrayDeserializer<T> extends ValueDeserializer<T> implements Cont
this.deserializeNullAsEmptyCollection = deserializeNullAsEmptyCollection;
}

abstract T create(List<Object> list, DeserializationContext ctxt) throws JsonMappingException;
abstract T create(List<Object> list, DeserializationContext ctxt) throws DatabindException;

/**
* Creates a new deserializer from the original one (this).
Expand All @@ -70,11 +68,11 @@ abstract class ArrayDeserializer<T> extends ValueDeserializer<T> implements Cont
* @return a new deserializer
*/
abstract ArrayDeserializer<T> createDeserializer(TypeDeserializer elementTypeDeserializer,
JsonDeserializer<?> elementDeserializer);
ValueDeserializer<?> elementDeserializer);

@Override
public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException {
JsonDeserializer<?> elementDeser = elementDeserializer;
public ValueDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) throws DatabindException {
ValueDeserializer<?> elementDeser = elementDeserializer;
TypeDeserializer elementTypeDeser = elementTypeDeserializer;

if (elementDeser == null) {
Expand All @@ -89,9 +87,9 @@ public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanPro
}

@Override
public T deserialize(JsonParser parser, DeserializationContext context, T intoValue) throws IOException {
public T deserialize(JsonParser parser, DeserializationContext context, T intoValue) {
if (!parser.isExpectedStartArrayToken()) {
throw mappingException(context, collectionType.getRawClass(), parser.getCurrentToken());
throw mappingException(context, collectionType.getRawClass(), parser.currentToken());
}

List<Object> elements = new ArrayList<>();
Expand All @@ -117,19 +115,19 @@ public T deserialize(JsonParser parser, DeserializationContext context, T intoVa
}

@Override
public T deserialize(JsonParser parser, DeserializationContext context) throws IOException {
public T deserialize(JsonParser parser, DeserializationContext context) {
return deserialize(parser, context, null);
}

@Override
public T getNullValue(DeserializationContext ctxt) throws JsonMappingException {
public T getNullValue(DeserializationContext ctxt) throws DatabindException {
if (deserializeNullAsEmptyCollection) {
return create(Collections.emptyList(), ctxt);
}
return super.getNullValue(ctxt);
return (T) super.getNullValue(ctxt);
}

static void checkContainedTypeIsComparable(DeserializationContext ctxt, JavaType type) throws JsonMappingException {
static void checkContainedTypeIsComparable(DeserializationContext ctxt, JavaType type) throws DatabindException {
Class<?> clz = type.getRawClass();
if (clz == Object.class || !Comparable.class.isAssignableFrom(clz)) {
throw mappingException(ctxt, clz, null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,41 +19,38 @@
*/
package io.vavr.jackson.datatype.deserialize;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.deser.ResolvableDeserializer;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.type.TypeFactory;
import tools.jackson.core.JsonParser;
import tools.jackson.core.JsonToken;
import tools.jackson.databind.DeserializationContext;
import tools.jackson.databind.JavaType;
import tools.jackson.databind.ValueDeserializer;
import tools.jackson.databind.DatabindException;
import tools.jackson.databind.deser.std.StdDeserializer;
import tools.jackson.databind.type.TypeFactory;
import io.vavr.collection.CharSeq;

import java.io.IOException;

class CharSeqDeserializer extends StdDeserializer<CharSeq> implements ResolvableDeserializer {
class CharSeqDeserializer extends StdDeserializer<CharSeq> {

private static final long serialVersionUID = 1L;

private JsonDeserializer<?> deserializer;
private ValueDeserializer<?> deserializer;

CharSeqDeserializer(JavaType valueType) {
super(valueType);
}

@Override
public CharSeq deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
public CharSeq deserialize(JsonParser p, DeserializationContext ctxt) {
Object obj = deserializer.deserialize(p, ctxt);
if (obj instanceof String) {
return CharSeq.of((String) obj);
} else {
throw JsonMappingException.from(p, String.format("Unexpected token (%s), expected %s: CharSeq can only be deserialized from String", p.getCurrentToken(), JsonToken.VALUE_STRING));
throw DatabindException.from(p, String.format("Unexpected token (%s), expected %s: CharSeq can only be deserialized from String", p.currentToken(), JsonToken.VALUE_STRING));
}
}

@Override
public void resolve(DeserializationContext ctxt) throws JsonMappingException {
public void resolve(DeserializationContext ctxt) throws DatabindException {
deserializer = ctxt.findContextualValueDeserializer(TypeFactory.unknownType(), null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,36 +19,35 @@
*/
package io.vavr.jackson.datatype.deserialize;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;
import tools.jackson.core.JsonParser;
import tools.jackson.core.JsonToken;
import tools.jackson.databind.DeserializationContext;
import tools.jackson.databind.JavaType;
import tools.jackson.databind.DatabindException;
import io.vavr.control.Either;
import tools.jackson.databind.ValueDeserializer;

import java.io.IOException;
import static tools.jackson.core.JsonToken.END_ARRAY;
import static tools.jackson.core.JsonToken.END_OBJECT;
import static tools.jackson.core.JsonToken.START_ARRAY;
import static tools.jackson.core.JsonToken.START_OBJECT;
import static tools.jackson.core.JsonToken.VALUE_NULL;

import static com.fasterxml.jackson.core.JsonToken.END_ARRAY;
import static com.fasterxml.jackson.core.JsonToken.START_ARRAY;
import static com.fasterxml.jackson.core.JsonToken.START_OBJECT;
import static com.fasterxml.jackson.core.JsonToken.VALUE_NULL;

class EitherDeserializer extends ValueDeserializer<Either<?, ?>> {
class EitherDeserializer extends VavrValueDeserializer<Either<?, ?>> {

private static final long serialVersionUID = 1L;

private final JavaType javaType;
private JsonDeserializer<?> stringDeserializer;
private ValueDeserializer<?> stringDeserializer;

EitherDeserializer(JavaType valueType) {
super(valueType, 2);
this.javaType = valueType;
}

@Override
public Either<?, ?> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
final JsonToken nextToken = p.getCurrentToken();
public Either<?, ?> deserialize(JsonParser p, DeserializationContext ctxt) {
final JsonToken nextToken = p.currentToken();

if (nextToken == START_ARRAY) {
boolean right = false;
Expand All @@ -69,7 +68,7 @@ class EitherDeserializer extends ValueDeserializer<Either<?, ?>> {
}
break;
case 2:
JsonDeserializer<?> deserializer = right ? deserializer(1) : deserializer(0);
ValueDeserializer<?> deserializer = right ? deserializer(1) : deserializer(0);
value = (jsonToken != VALUE_NULL) ? deserializer.deserialize(p, ctxt) : deserializer.getNullValue(ctxt);
break;
}
Expand All @@ -79,26 +78,24 @@ class EitherDeserializer extends ValueDeserializer<Either<?, ?>> {
}
return right ? Either.right(value) : Either.left(value);
} else if (nextToken == START_OBJECT) {
final JsonToken currentToken = p.getCurrentToken();
final String type = p.nextFieldName();
final JsonToken currentToken = p.currentToken();
final String type = p.nextName();
if (isRight(type)) {
final JsonDeserializer<?> deserializer = deserializer(1);
final Object value = p.nextToken() != VALUE_NULL ? deserializer.deserialize(p, ctxt) : deserializer.getNullValue(ctxt);
return Either.right(value);
return Either.right(getValue(p, ctxt, 1));
} else if (isLeft(type)) {
final JsonDeserializer<?> deserializer = deserializer(0);
final Object value = p.nextToken() != VALUE_NULL ? deserializer.deserialize(p, ctxt) : deserializer.getNullValue(ctxt);
return Either.left(value);
return Either.left(getValue(p, ctxt, 0));
} else {
throw mappingException(ctxt, javaType.getRawClass(), currentToken);
}
} else {
throw mappingException(ctxt, javaType.getRawClass(), p.getCurrentToken());
throw mappingException(ctxt, javaType.getRawClass(), p.currentToken());
}
}



@Override
public void resolve(DeserializationContext ctxt) throws JsonMappingException {
public void resolve(DeserializationContext ctxt) throws DatabindException {
super.resolve(ctxt);
stringDeserializer = ctxt.findContextualValueDeserializer(ctxt.constructType(String.class), null);
}
Expand All @@ -110,4 +107,13 @@ private static boolean isRight(final String fieldName) {
private static boolean isLeft(final String fieldName) {
return "left".equals(fieldName) || "l".equals(fieldName);
}

private Object getValue(JsonParser p, DeserializationContext ctxt, int index) {
final ValueDeserializer<?> deserializer = deserializer(index);
final Object value = p.nextToken() != VALUE_NULL ? deserializer.deserialize(p, ctxt) : deserializer.getNullValue(ctxt);
if (p.nextToken() != END_OBJECT) {
throw mappingException(ctxt, javaType.getRawClass(), p.currentToken());
}
return value;
}
}
Loading