Skip to content
This repository has been archived by the owner on Nov 7, 2019. It is now read-only.

Commit

Permalink
Merge branch 'master' of github.com:FasterXML/jackson-datatype-jdk8
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed Oct 29, 2016
2 parents 6d74ba7 + ba9c7e9 commit 3d819a1
Show file tree
Hide file tree
Showing 15 changed files with 130 additions and 128 deletions.
Expand Up @@ -9,16 +9,13 @@

class Jdk8Deserializers extends Deserializers.Base
{
// 21-Oct-2015, tatu: Code much simplified with 2.7 where we should be getting much
// of boilerplate handling automatically

@Override // since 2.7
public JsonDeserializer<?> findReferenceDeserializer(ReferenceType refType,
DeserializationConfig config, BeanDescription beanDesc,
TypeDeserializer contentTypeDeserializer, JsonDeserializer<?> contentDeserializer)
{
if (refType.hasRawClass(Optional.class)) {
return new OptionalDeserializer(refType, contentTypeDeserializer,contentDeserializer);
return new OptionalDeserializer(refType, null, contentTypeDeserializer,contentDeserializer);
}
// 21-Oct-2015, tatu: Should probably consider possibility of custom deserializer being
// added to property; if so, `contentDeserializer` would not be null.
Expand Down
@@ -1,126 +1,65 @@
package com.fasterxml.jackson.datatype.jdk8;

import java.io.IOException;
import java.util.Optional;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.deser.ValueInstantiator;
import com.fasterxml.jackson.databind.deser.std.ReferenceTypeDeserializer;
import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;

final class OptionalDeserializer
extends StdDeserializer<Optional<?>>
implements ContextualDeserializer
extends ReferenceTypeDeserializer<Optional<?>>
{
private static final long serialVersionUID = 1L;

protected final JavaType _fullType;

protected final JsonDeserializer<?> _valueDeserializer;
protected final TypeDeserializer _valueTypeDeserializer;

/*
/**********************************************************
/* Life-cycle
/**********************************************************
*/

public OptionalDeserializer(JavaType fullType,
TypeDeserializer typeDeser, JsonDeserializer<?> valueDeser)
{
super(fullType);
_fullType = fullType;
_valueTypeDeserializer = typeDeser;
_valueDeserializer = valueDeser;
}

/**
* Overridable fluent factory method used for creating contextual
* instances.
* @since 2.9
*/
protected OptionalDeserializer withResolved(TypeDeserializer typeDeser,
JsonDeserializer<?> valueDeser)
public OptionalDeserializer(JavaType fullType, ValueInstantiator inst,
TypeDeserializer typeDeser, JsonDeserializer<?> deser)
{
if ((valueDeser == _valueDeserializer) && (typeDeser == _valueTypeDeserializer)) {
return this;
}
return new OptionalDeserializer(_fullType, typeDeser, valueDeser);
}

/**
* Method called to finalize setup of this deserializer,
* after deserializer itself has been registered. This
* is needed to handle recursive and transitive dependencies.
*/
@Override
public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
BeanProperty property) throws JsonMappingException
{
JsonDeserializer<?> deser = _valueDeserializer;
TypeDeserializer typeDeser = _valueTypeDeserializer;
JavaType refType = _fullType.getReferencedType();

if (deser == null) {
deser = ctxt.findContextualValueDeserializer(refType, property);
} else { // otherwise directly assigned, probably not contextual yet:
deser = ctxt.handleSecondaryContextualization(deser, property, refType);
}
if (typeDeser != null) {
typeDeser = typeDeser.forProperty(property);
}
return withResolved(typeDeser, deser);
super(fullType, inst, typeDeser, deser);
}

/*
/**********************************************************
/* Overridden accessors
/* Abstract method implementations
/**********************************************************
*/

@Override
public JavaType getValueType() { return _fullType; }
public OptionalDeserializer withResolved(TypeDeserializer typeDeser, JsonDeserializer<?> valueDeser) {
return new OptionalDeserializer(_fullType, _valueInstantiator,
typeDeser, valueDeser);
}

@Override
public Optional<?> getNullValue(DeserializationContext ctxt) {
return Optional.empty();
}

/*
/**********************************************************
/* Deserialization
/**********************************************************
*/

@Override
public Optional<?> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
Object refd = (_valueTypeDeserializer == null)
? _valueDeserializer.deserialize(p, ctxt)
: _valueDeserializer.deserializeWithType(p, ctxt, _valueTypeDeserializer);
return Optional.ofNullable(refd);
public Optional<?> referenceValue(Object contents) {
return Optional.ofNullable(contents);
}

@Override
public Optional<?> deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer)
throws IOException
{
final JsonToken t = p.getCurrentToken();
if (t == JsonToken.VALUE_NULL) {
return getNullValue(ctxt);
}
// 03-Nov-2013, tatu: This gets rather tricky with "natural" types
// (String, Integer, Boolean), which do NOT include type information.
// These might actually be handled ok except that nominal type here
// is `Optional`, so special handling is not invoked; instead, need
// to do a work-around here.
// 22-Oct-2015, tatu: Most likely this is actually wrong, result of incorrect
// serialization (up to 2.6, was omitting necessary type info after all);
// but safest to leave in place for now
if (t != null && t.isScalarValue()) {
return deserialize(p, ctxt);
}
return (Optional<?>) typeDeserializer.deserializeTypedFromAny(p, ctxt);
public Object getReferenced(Optional<?> reference) {
return reference.get();
}

@Override // since 2.9
public Optional<?> updateReference(Optional<?> reference, Object contents) {
return Optional.ofNullable(contents);
}

// Default ought to be fine:
// public Boolean supportsUpdate(DeserializationConfig config) { }

}
Expand Up @@ -5,9 +5,9 @@

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer;

final class OptionalDoubleDeserializer extends StdDeserializer<OptionalDouble>
final class OptionalDoubleDeserializer extends StdScalarDeserializer<OptionalDouble>
{
private static final long serialVersionUID = 1L;

Expand All @@ -23,7 +23,7 @@ public OptionalDouble getNullValue(DeserializationContext ctxt) {
}

@Override
public OptionalDouble deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
return OptionalDouble.of(jp.getValueAsDouble());
public OptionalDouble deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
return OptionalDouble.of(p.getValueAsDouble());
}
}
Expand Up @@ -10,9 +10,9 @@
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonNumberFormatVisitor;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer;

public class OptionalDoubleSerializer extends StdSerializer<OptionalDouble>
public class OptionalDoubleSerializer extends StdScalarSerializer<OptionalDouble>
{
private static final long serialVersionUID = 1L;

Expand Down
Expand Up @@ -5,9 +5,9 @@

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer;

public class OptionalIntDeserializer extends StdDeserializer<OptionalInt>
public class OptionalIntDeserializer extends StdScalarDeserializer<OptionalInt>
{
private static final long serialVersionUID = 1L;

Expand All @@ -23,7 +23,7 @@ public OptionalInt getNullValue(DeserializationContext ctxt) {
}

@Override
public OptionalInt deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
return OptionalInt.of(jp.getValueAsInt());
public OptionalInt deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
return OptionalInt.of(p.getValueAsInt());
}
}
Expand Up @@ -10,9 +10,9 @@
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonIntegerFormatVisitor;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer;

final class OptionalIntSerializer extends StdSerializer<OptionalInt>
final class OptionalIntSerializer extends StdScalarSerializer<OptionalInt>
{
private static final long serialVersionUID = 1L;

Expand All @@ -22,7 +22,6 @@ public OptionalIntSerializer() {
super(OptionalInt.class);
}

// @since 2.6
@Override
public boolean isEmpty(SerializerProvider provider, OptionalInt value) {
return (value == null) || !value.isPresent();
Expand Down
Expand Up @@ -5,9 +5,9 @@

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer;

public class OptionalLongDeserializer extends StdDeserializer<OptionalLong>
public class OptionalLongDeserializer extends StdScalarDeserializer<OptionalLong>
{
private static final long serialVersionUID = 1L;

Expand All @@ -23,7 +23,7 @@ public OptionalLong getNullValue(DeserializationContext ctxt) {
}

@Override
public OptionalLong deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
return OptionalLong.of(jp.getLongValue());
public OptionalLong deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
return OptionalLong.of(p.getLongValue());
}
}
Expand Up @@ -10,9 +10,9 @@
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonIntegerFormatVisitor;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer;

final class OptionalLongSerializer extends StdSerializer<OptionalLong>
final class OptionalLongSerializer extends StdScalarSerializer<OptionalLong>
{
private static final long serialVersionUID = 1L;

Expand Down
Expand Up @@ -38,11 +38,6 @@ protected ReferenceTypeSerializer<Optional<?>> withResolved(BeanProperty prop,
TypeSerializer vts, JsonSerializer<?> valueSer,
NameTransformer unwrapper)
{
if ((_property == prop)
&& (_valueTypeSerializer == vts) && (_valueSerializer == valueSer)
&& (_unwrapper == unwrapper)) {
return this;
}
return new OptionalSerializer(this, prop, vts, valueSer, unwrapper,
_suppressableValue, _suppressNulls);
}
Expand All @@ -51,10 +46,6 @@ protected ReferenceTypeSerializer<Optional<?>> withResolved(BeanProperty prop,
public ReferenceTypeSerializer<Optional<?>> withContentInclusion(Object suppressableValue,
boolean suppressNulls)
{
if ((_suppressableValue == suppressableValue)
&& (_suppressNulls == suppressNulls)) {
return this;
}
return new OptionalSerializer(this, _property, _valueTypeSerializer,
_valueSerializer, _unwrapper,
suppressableValue, suppressNulls);
Expand Down
@@ -1,4 +1,4 @@
package com.fasterxml.jackson.datatype.jdk8;
package com.fasterxml.jackson.datatype.jdk8.optional;

import java.util.*;

Expand All @@ -8,6 +8,8 @@
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jdk8.ModuleTestBase;

public class OptionalBasicTest extends ModuleTestBase
{
Expand Down
@@ -0,0 +1,71 @@
package com.fasterxml.jackson.datatype.jdk8.optional;

import java.util.Optional;

import com.fasterxml.jackson.annotation.JsonSetter;
import com.fasterxml.jackson.annotation.OptBoolean;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jdk8.ModuleTestBase;

public class OptionalMergingTest extends ModuleTestBase
{
static class MergedStringReference
{
@JsonSetter(merge=OptBoolean.TRUE)
public Optional<String> value = Optional.of("default");
}

static class MergedPOJOReference
{
@JsonSetter(merge=OptBoolean.TRUE)
public Optional<POJO> value;

protected MergedPOJOReference() {
value = Optional.of(new POJO(7, 2));
}

public MergedPOJOReference(int x, int y) {
value = Optional.of(new POJO(x, y));
}
}

static class POJO {
public int x, y;

protected POJO() { }
public POJO(int x, int y) {
this.x = x;
this.y = y;
}
}

/*
/**********************************************************************
/* Test methods
/**********************************************************************
*/

private final ObjectMapper MAPPER = mapperWithModule();

public void testStringReferenceMerging() throws Exception
{
MergedStringReference result = MAPPER.readValue(aposToQuotes("{'value':'override'}"),
MergedStringReference.class);
assertEquals("override", result.value.get());
}

public void testPOJOReferenceMerging() throws Exception
{
MergedPOJOReference result = MAPPER.readValue(aposToQuotes("{'value':{'y':-6}}"),
MergedPOJOReference.class);
assertEquals(7, result.value.get().x);
assertEquals(-6, result.value.get().y);

// Also should retain values we pass
result = MAPPER.readerForUpdating(new MergedPOJOReference(10, 20))
.readValue(aposToQuotes("{'value':{'x':11}}"));
assertEquals(11, result.value.get().x);
assertEquals(20, result.value.get().y);
}
}

0 comments on commit 3d819a1

Please sign in to comment.