Skip to content

Commit

Permalink
Merge branch '2.19'
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed Nov 5, 2024
2 parents 2b69a8f + a29cda6 commit bc231c8
Show file tree
Hide file tree
Showing 11 changed files with 682 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
import tools.jackson.datatype.guava.deser.multimap.list.LinkedListMultimapDeserializer;
import tools.jackson.datatype.guava.deser.multimap.set.HashMultimapDeserializer;
import tools.jackson.datatype.guava.deser.multimap.set.LinkedHashMultimapDeserializer;
import tools.jackson.datatype.guava.deser.table.HashBasedTableDeserializer;
import tools.jackson.datatype.guava.deser.table.ImmutableTableDeserializer;
import tools.jackson.datatype.guava.deser.table.TreeBasedTableDeserializer;
import tools.jackson.datatype.guava.util.ImmutablePrimitiveTypes;
import tools.jackson.datatype.guava.util.PrimitiveTypes;

Expand Down Expand Up @@ -259,8 +262,15 @@ public ValueDeserializer<?> findMapLikeDeserializer(MapLikeType type,
}

if (Table.class.isAssignableFrom(raw)) {
// !!! TODO
if (HashBasedTable.class.isAssignableFrom(raw)) {
return new HashBasedTableDeserializer(type);
}
if (TreeBasedTable.class.isAssignableFrom(raw)) {
return new TreeBasedTableDeserializer(type);
}
return new ImmutableTableDeserializer(type);
}

// @since 2.16 : support Cache deserialization
java.util.Optional<ValueDeserializer<?>> cacheDeserializer = findCacheDeserializer(raw, type, config,
beanDesc, keyDeserializer, elementTypeDeserializer, elementDeserializer);
Expand Down Expand Up @@ -315,7 +325,7 @@ public ValueDeserializer<?> findReferenceDeserializer(ReferenceType refType,
public ValueDeserializer<?> findBeanDeserializer(final JavaType type, DeserializationConfig config,
BeanDescription beanDesc)
{
if (RangeSet.class.isAssignableFrom(type.getRawClass())) {
if (type.isTypeOrSubTypeOf(RangeSet.class)) {
return new RangeSetDeserializer();
}
if (type.hasRawClass(Range.class)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,7 @@ public ValueSerializer<?> findReferenceSerializer(SerializationConfig config,
ReferenceType refType, BeanDescription beanDesc, JsonFormat.Value formatOverrides,
TypeSerializer contentTypeSerializer, ValueSerializer<Object> contentValueSerializer)
{
final Class<?> raw = refType.getRawClass();
if (Optional.class.isAssignableFrom(raw)) {
if (refType.isTypeOrSubTypeOf(Optional.class)) {
boolean staticTyping = (contentTypeSerializer == null)
&& config.isEnabled(MapperFeature.USE_STATIC_TYPING);
return new GuavaOptionalSerializer(refType, staticTyping,
Expand All @@ -71,34 +70,30 @@ public ValueSerializer<?> findReferenceSerializer(SerializationConfig config,
public ValueSerializer<?> findSerializer(SerializationConfig config, JavaType type,
BeanDescription beanDesc, JsonFormat.Value formatOverrides)
{
Class<?> raw = type.getRawClass();
if (RangeSet.class.isAssignableFrom(raw)) {
if (type.isTypeOrSubTypeOf(RangeSet.class)) {
return new RangeSetSerializer();
}
if (Range.class.isAssignableFrom(raw)) {
if (type.isTypeOrSubTypeOf(Range.class)) {
return new RangeSerializer(_findDeclared(type, Range.class));
}
if (Table.class.isAssignableFrom(raw)) {
return new TableSerializer(_findDeclared(type, Table.class));
}
if (HostAndPort.class.isAssignableFrom(raw)) {
if (type.isTypeOrSubTypeOf(HostAndPort.class)) {
return ToStringSerializer.instance;
}
if (InternetDomainName.class.isAssignableFrom(raw)) {
if (type.isTypeOrSubTypeOf(InternetDomainName.class)) {
return ToStringSerializer.instance;
}
// not sure how useful, but why not?
if (CacheBuilderSpec.class.isAssignableFrom(raw) || CacheBuilder.class.isAssignableFrom(raw)) {
if (type.isTypeOrSubTypeOf(CacheBuilderSpec.class) || type.isTypeOrSubTypeOf(CacheBuilder.class)) {
return ToStringSerializer.instance;
}
if (HashCode.class.isAssignableFrom(raw)) {
if (type.isTypeOrSubTypeOf(HashCode.class)) {
return ToStringSerializer.instance;
}
if (FluentIterable.class.isAssignableFrom(raw)) {
if (type.isTypeOrSubTypeOf(FluentIterable.class)) {
JavaType iterableType = _findDeclared(type, Iterable.class);
return new StdDelegatingSerializer(FluentConverter.instance, iterableType, null, null);
}
return ImmutablePrimitiveTypes.isAssignableFromImmutableArray(raw)
return ImmutablePrimitiveTypes.isAssignableFromImmutableArray(type.getRawClass())
.transform(ImmutablePrimitiveTypes.ImmutablePrimitiveArrays::newSerializer)
.orNull();
}
Expand All @@ -109,7 +104,7 @@ public ValueSerializer<?> findMapLikeSerializer(SerializationConfig config,
ValueSerializer<Object> keySerializer,
TypeSerializer elementTypeSerializer, ValueSerializer<Object> elementValueSerializer)
{
if (Multimap.class.isAssignableFrom(type.getRawClass())) {
if (type.isTypeOrSubTypeOf(Multimap.class)) {
final AnnotationIntrospector intr = config.getAnnotationIntrospector();
Object filterId = intr.findFilterId(config, (Annotated)beanDesc.getClassInfo());
JsonIgnoreProperties.Value ignorals = config.getDefaultPropertyIgnorals(Multimap.class,
Expand All @@ -118,7 +113,7 @@ public ValueSerializer<?> findMapLikeSerializer(SerializationConfig config,
return new MultimapSerializer(type, beanDesc,
keySerializer, elementTypeSerializer, elementValueSerializer, ignored, filterId);
}
if (Cache.class.isAssignableFrom(type.getRawClass())) {
if (type.isTypeOrSubTypeOf(Cache.class)) {
final AnnotationIntrospector intr = config.getAnnotationIntrospector();
Object filterId = intr.findFilterId(config, (Annotated)beanDesc.getClassInfo());
JsonIgnoreProperties.Value ignorals = config.getDefaultPropertyIgnorals(Cache.class,
Expand All @@ -127,6 +122,9 @@ public ValueSerializer<?> findMapLikeSerializer(SerializationConfig config,
return new CacheSerializer(type, beanDesc,
keySerializer, elementTypeSerializer, elementValueSerializer, ignored, filterId);
}
if (type.isTypeOrSubTypeOf(Table.class)) {
return new TableSerializer(type);
}
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,19 @@ public JavaType modifyType(JavaType type, Type jdkType, TypeBindings bindings, T
if (raw == Optional.class) {
return ReferenceType.upgradeFrom(type, type.containedTypeOrUnknown(0));
}
if (raw == Table.class) {
MapLikeType columnValueType =
MapLikeType.upgradeFrom(
type,
type.containedTypeOrUnknown(1),
type.containedTypeOrUnknown(2)
);
return MapLikeType.upgradeFrom(
type,
type.containedTypeOrUnknown(0),
columnValueType
);
}
return type;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package tools.jackson.datatype.guava.deser.table;

import tools.jackson.databind.ValueDeserializer;
import tools.jackson.databind.KeyDeserializer;
import tools.jackson.databind.deser.NullValueProvider;
import tools.jackson.databind.jsontype.TypeDeserializer;
import tools.jackson.databind.type.MapLikeType;

import com.google.common.collect.HashBasedTable;

/**
* Provides deserialization for the Guava HashBasedTable class.
*
* @author Abhishekkr3003
*/
public class HashBasedTableDeserializer
extends MutableTableDeserializer<HashBasedTable<Object, Object, Object>>
{
public HashBasedTableDeserializer(MapLikeType type) {
super(type);
}

public HashBasedTableDeserializer(MapLikeType type, KeyDeserializer rowDeserializer,
KeyDeserializer columnDeserializer, TypeDeserializer elementTypeDeserializer,
ValueDeserializer<?> elementDeserializer, NullValueProvider nvp) {
super(type, rowDeserializer, columnDeserializer, elementTypeDeserializer,
elementDeserializer, nvp
);
}

@Override
protected HashBasedTable<Object, Object, Object> createTable() {
return HashBasedTable.create();
}

@Override
protected ValueDeserializer<?> _createContextual(MapLikeType type,
KeyDeserializer rowDeserializer,
KeyDeserializer columnDeserializer, TypeDeserializer typeDeserializer,
ValueDeserializer<?> elementDeserializer, NullValueProvider nvp) {
return new HashBasedTableDeserializer(type,
rowDeserializer, columnDeserializer, typeDeserializer, elementDeserializer, nvp);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package tools.jackson.datatype.guava.deser.table;

import tools.jackson.core.JsonParser;
import tools.jackson.core.JsonToken;

import tools.jackson.databind.DeserializationContext;
import tools.jackson.databind.ValueDeserializer;
import tools.jackson.databind.KeyDeserializer;
import tools.jackson.databind.deser.NullValueProvider;
import tools.jackson.databind.jsontype.TypeDeserializer;
import tools.jackson.databind.type.MapLikeType;
import tools.jackson.databind.util.AccessPattern;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableTable;

/**
* Provides deserialization for the Guava ImmutableTable class.
*
* @author Abhishekkr3003
*/
public class ImmutableTableDeserializer
extends TableDeserializer<ImmutableTable<Object, Object, Object>>
{
public ImmutableTableDeserializer(MapLikeType type) {
super(type);
}

protected ImmutableTableDeserializer(MapLikeType type, KeyDeserializer rowDeserializer,
KeyDeserializer colDeserializer, ValueDeserializer<?> valueDeserializer,
TypeDeserializer valueTypeDeserializer, NullValueProvider nuller) {
super(type, rowDeserializer, colDeserializer, valueTypeDeserializer, valueDeserializer,
nuller
);
}

@Override
public AccessPattern getEmptyAccessPattern() {
// immutable, hence:
return AccessPattern.CONSTANT;
}


@Override
public Object getEmptyValue(DeserializationContext ctxt) {
return ImmutableMap.of();
}

protected ImmutableTable.Builder<Object, Object, Object> createBuilder() {
return ImmutableTable.builder();
}

@Override
public ImmutableTable<Object, Object, Object> deserialize(JsonParser p,
DeserializationContext ctxt)
{
ImmutableTable.Builder<Object, Object, Object> table = createBuilder();

JsonToken currToken = p.currentToken();
if (currToken != JsonToken.PROPERTY_NAME && currToken != JsonToken.END_OBJECT) {
expect(ctxt, JsonToken.START_OBJECT, currToken);
currToken = p.nextToken();
}

for (; currToken == JsonToken.PROPERTY_NAME; currToken = p.nextToken()) {
final Object rowKey;
if (_rowDeserializer != null) {
rowKey = _rowDeserializer.deserializeKey(p.currentName(), ctxt);
} else {
rowKey = p.currentName();
}

currToken = p.nextToken();
expect(ctxt, JsonToken.START_OBJECT, currToken);

for (
currToken = p.nextToken(); currToken == JsonToken.PROPERTY_NAME;
currToken = p.nextToken()) {
final Object colKey;
if (_colDeserializer != null) {
colKey = _colDeserializer.deserializeKey(p.currentName(), ctxt);
} else {
colKey = p.currentName();
}

p.nextToken();

final Object value;
if (p.currentToken() == JsonToken.VALUE_NULL) {
if (_skipNullValues) {
continue;
}
value = _nullProvider.getNullValue(ctxt);
} else if (_valueTypeDeserializer != null) {
value = _valueDeserializer.deserializeWithType(p, ctxt, _valueTypeDeserializer);
} else {
value = _valueDeserializer.deserialize(p, ctxt);
}
table.put(rowKey, colKey, value);
}
expect(ctxt, JsonToken.END_OBJECT, p.currentToken());
}
return table.build();
}

@Override
protected ValueDeserializer<?> _createContextual(MapLikeType type,
KeyDeserializer rowDeserializer,
KeyDeserializer columnDeserializer, TypeDeserializer valueTypeDeserializer,
ValueDeserializer<?> valueDeserializer, NullValueProvider nullValueProvider) {
return new ImmutableTableDeserializer(type, rowDeserializer, columnDeserializer,
valueDeserializer, valueTypeDeserializer, nullValueProvider
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package tools.jackson.datatype.guava.deser.table;

import tools.jackson.core.JsonParser;
import tools.jackson.core.JsonToken;
import tools.jackson.databind.DeserializationContext;
import tools.jackson.databind.KeyDeserializer;
import tools.jackson.databind.ValueDeserializer;
import tools.jackson.databind.deser.NullValueProvider;
import tools.jackson.databind.jsontype.TypeDeserializer;
import tools.jackson.databind.type.MapLikeType;

import com.google.common.collect.Table;

/**
* @author Abhishekkr3003
*/
public abstract class MutableTableDeserializer<T extends Table<Object, Object, Object>>
extends TableDeserializer<T>
{
protected MutableTableDeserializer(MapLikeType type) {
super(type);
}

protected MutableTableDeserializer(MapLikeType _type, KeyDeserializer _rowDeserializer,
KeyDeserializer _colDeserializer, TypeDeserializer _valueTypeDeserializer,
ValueDeserializer<?> _valueDeserializer, NullValueProvider nvp) {
super(
_type, _rowDeserializer, _colDeserializer, _valueTypeDeserializer, _valueDeserializer,
nvp
);
}

protected abstract T createTable();

@Override
protected abstract ValueDeserializer<?> _createContextual(MapLikeType t, KeyDeserializer rkd,
KeyDeserializer ckd, TypeDeserializer vtd, ValueDeserializer<?> vd, NullValueProvider np);

@Override
public T deserialize(JsonParser p, DeserializationContext ctxt) {
T table = createTable();

JsonToken currToken = p.currentToken();
if (currToken != JsonToken.PROPERTY_NAME && currToken != JsonToken.END_OBJECT) {
expect(ctxt, JsonToken.START_OBJECT, currToken);
currToken = p.nextToken();
}

for (; currToken == JsonToken.PROPERTY_NAME; currToken = p.nextToken()) {
final Object rowKey;
if (_rowDeserializer != null) {
rowKey = _rowDeserializer.deserializeKey(p.currentName(), ctxt);
} else {
rowKey = p.currentName();
}

currToken = p.nextToken();
expect(ctxt, JsonToken.START_OBJECT, currToken);

for (
currToken = p.nextToken(); currToken == JsonToken.PROPERTY_NAME;
currToken = p.nextToken()) {
final Object colKey;
if (_colDeserializer != null) {
colKey = _colDeserializer.deserializeKey(p.currentName(), ctxt);
} else {
colKey = p.currentName();
}

p.nextToken();

final Object value;
if (p.currentToken() == JsonToken.VALUE_NULL) {
if (_skipNullValues) {
continue;
}
value = _nullProvider.getNullValue(ctxt);
} else if (_valueTypeDeserializer != null) {
value = _valueDeserializer.deserializeWithType(p, ctxt, _valueTypeDeserializer);
} else {
value = _valueDeserializer.deserialize(p, ctxt);
}
table.put(rowKey, colKey, value);
}
expect(ctxt, JsonToken.END_OBJECT, p.currentToken());
}
return table;
}
}
Loading

0 comments on commit bc231c8

Please sign in to comment.