Skip to content

Commit

Permalink
Add @JsonAnyGetter and @JsonAnySetter support
Browse files Browse the repository at this point in the history
  • Loading branch information
nmorel committed Dec 6, 2014
1 parent e831d56 commit 4ae5919
Show file tree
Hide file tree
Showing 24 changed files with 763 additions and 96 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.util.Map.Entry;
import java.util.Set;

import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
Expand Down Expand Up @@ -56,6 +57,8 @@ public abstract class AbstractBeanJsonDeserializer<T> extends JsonDeserializer<T

private final Map<Class, SubtypeDeserializer> subtypeClassToDeserializer;

private final AnySetterDeserializer<T, ?> anySetterDeserializer;

protected AbstractBeanJsonDeserializer() {
this.instanceBuilder = initInstanceBuilder();
this.deserializers = initDeserializers();
Expand All @@ -65,6 +68,7 @@ protected AbstractBeanJsonDeserializer() {
this.defaultIdentityInfo = initIdentityInfo();
this.defaultTypeInfo = initTypeInfo();
this.subtypeClassToDeserializer = initMapSubtypeClassToDeserializer();
this.anySetterDeserializer = initAnySetterDeserializer();
}

/**
Expand Down Expand Up @@ -125,6 +129,13 @@ protected Map<Class, SubtypeDeserializer> initMapSubtypeClassToDeserializer() {
return Collections.emptyMap();
}

/**
* Initialize the {@link AnySetterDeserializer}. Returns null if there is no method annoted with {@link JsonAnySetter} on bean.
*/
protected AnySetterDeserializer<T, ?> initAnySetterDeserializer() {
return null;
}

/**
* Whether encountering of unknown
* properties should result in a failure (by throwing a
Expand Down Expand Up @@ -302,10 +313,12 @@ public final T deserializeInline( final JsonReader reader, final JsonDeserializa
}

BeanPropertyDeserializer<T, ?> property = getPropertyDeserializer( propertyName, ctx, ignoreUnknown );
if ( null == property ) {
reader.skipValue();
} else {
if ( null != property ) {
property.deserialize( reader, bean, ctx );
} else if ( null != anySetterDeserializer ) {
anySetterDeserializer.deserialize( reader, bean, propertyName, ctx );
} else {
reader.skipValue();
}
}

Expand All @@ -315,8 +328,8 @@ public final T deserializeInline( final JsonReader reader, final JsonDeserializa
return bean;
}

private Map<String, String> readIdentityProperty( IdentityDeserializationInfo identityInfo, T bean, Map<String,
String> bufferedProperties, JsonReader reader, final JsonDeserializationContext ctx, Set<String> ignoredProperties ) {
private Map<String, String> readIdentityProperty( IdentityDeserializationInfo identityInfo, T bean, Map<String, String>
bufferedProperties, JsonReader reader, final JsonDeserializationContext ctx, Set<String> ignoredProperties ) {
if ( null == identityInfo ) {
return bufferedProperties;
}
Expand Down Expand Up @@ -389,25 +402,27 @@ private void flushBufferedProperties( T bean, Map<String, String> bufferedProper
BeanPropertyDeserializer<T, ?> property = getPropertyDeserializer( propertyName, ctx, ignoreUnknown );
if ( null != property ) {
property.deserialize( ctx.newJsonReader( bufferedProperty.getValue() ), bean, ctx );
} else if ( null != anySetterDeserializer ) {
anySetterDeserializer.deserialize( ctx.newJsonReader( bufferedProperty.getValue() ), bean, propertyName, ctx );
}
}
}
}

private BeanPropertyDeserializer<T, ?> getPropertyDeserializer( String propertyName, JsonDeserializationContext ctx,
boolean ignoreUnknown ) {
private BeanPropertyDeserializer<T, ?> getPropertyDeserializer( String propertyName, JsonDeserializationContext ctx, boolean
ignoreUnknown ) {
BeanPropertyDeserializer<T, ?> property = deserializers.get( propertyName );
if ( null == property ) {
if ( !ignoreUnknown && ctx.isFailOnUnknownProperties() ) {
if ( !ignoreUnknown && ctx.isFailOnUnknownProperties() && null == anySetterDeserializer ) {
throw ctx.traceError( "Unknown property '" + propertyName + "'" );
}
}
return property;
}

private InternalDeserializer<T, ? extends JsonDeserializer<T>> getDeserializer( JsonReader reader, JsonDeserializationContext ctx,
TypeDeserializationInfo typeInfo,
String typeInformation ) {
TypeDeserializationInfo typeInfo, String
typeInformation ) {
Class typeClass = typeInfo.getTypeClass( typeInformation );
if ( null == typeClass ) {
throw ctx.traceError( "Could not find the type associated to " + typeInformation, reader );
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright 2014 Nicolas Morel
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.github.nmorel.gwtjackson.client.deser.bean;

import com.github.nmorel.gwtjackson.client.JsonDeserializationContext;
import com.github.nmorel.gwtjackson.client.JsonDeserializer;
import com.github.nmorel.gwtjackson.client.stream.JsonReader;

/**
* Deserializes a bean's property
*
* @author Nicolas Morel
*/
public abstract class AnySetterDeserializer<T, V> extends HasDeserializerAndParameters<V, JsonDeserializer<V>> {

/**
* Deserializes the property defined for this instance.
*
* @param reader reader
* @param bean bean to set the deserialized property to
* @param propertyName name of the property
* @param ctx context of the deserialization process
*/
public void deserialize( JsonReader reader, T bean, String propertyName, JsonDeserializationContext ctx ) {
setValue( bean, propertyName, deserialize( reader, ctx ), ctx );
}

public abstract void setValue( T bean, String propertyName, V value, JsonDeserializationContext ctx );
}

Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@
import java.util.Set;
import java.util.logging.Level;

import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
import com.github.nmorel.gwtjackson.client.JsonSerializationContext;
import com.github.nmorel.gwtjackson.client.JsonSerializer;
import com.github.nmorel.gwtjackson.client.JsonSerializerParameters;
Expand All @@ -45,11 +45,14 @@ public abstract class AbstractBeanJsonSerializer<T> extends JsonSerializer<T> im

private final TypeSerializationInfo<T> defaultTypeInfo;

private final AnyGetterPropertySerializer<T> anyGetterPropertySerializer;

protected AbstractBeanJsonSerializer() {
this.serializers = initSerializers();
this.defaultIdentityInfo = initIdentityInfo();
this.defaultTypeInfo = initTypeInfo();
this.subtypeClassToSerializer = initMapSubtypeClassToSerializer();
this.anyGetterPropertySerializer = initAnyGetterPropertySerializer();
}

/**
Expand Down Expand Up @@ -81,6 +84,13 @@ protected Map<Class, SubtypeSerializer> initMapSubtypeClassToSerializer() {
return Collections.emptyMap();
}

/**
* Initialize the {@link AnyGetterPropertySerializer}. Returns null if there is no method annoted with {@link JsonAnyGetter} on bean.
*/
protected AnyGetterPropertySerializer<T> initAnyGetterPropertySerializer() {
return null;
}

public abstract Class getSerializedType();

@Override
Expand Down Expand Up @@ -225,6 +235,10 @@ protected void serializeObject( JsonWriter writer, T value, JsonSerializationCon
}
}

if ( null != anyGetterPropertySerializer ) {
anyGetterPropertySerializer.serialize( writer, value, ctx );
}

writer.endObject();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright 2014 Nicolas Morel
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.github.nmorel.gwtjackson.client.ser.bean;

import java.util.Map;

import com.github.nmorel.gwtjackson.client.JsonSerializationContext;
import com.github.nmorel.gwtjackson.client.ser.map.MapJsonSerializer;
import com.github.nmorel.gwtjackson.client.stream.JsonWriter;

/**
* Serializes a bean's property
*
* @author Nicolas Morel
*/
public abstract class AnyGetterPropertySerializer<T> extends BeanPropertySerializer<T, Map> {

protected abstract MapJsonSerializer newSerializer();

/**
* Serializes the property defined for this instance.
*
* @param writer writer
* @param bean bean containing the property to serialize
* @param ctx context of the serialization process
*/
public void serialize( JsonWriter writer, T bean, JsonSerializationContext ctx ) {
Map map = getValue( bean, ctx );
if(null != map) {
((MapJsonSerializer) getSerializer()).serializeValues( writer, map, ctx, getParameters() );
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ protected MapJsonSerializer( KeySerializer<K> keySerializer, JsonSerializer<V> v
public void doSerialize( JsonWriter writer, @Nonnull M values, JsonSerializationContext ctx, JsonSerializerParameters params ) {
writer.beginObject();

serializeValues( writer, values, ctx, params );

writer.endObject();
}

public void serializeValues( JsonWriter writer, M values, JsonSerializationContext ctx, JsonSerializerParameters params ) {
if ( !values.isEmpty() ) {
Map<K, V> map = values;
if ( ctx.isOrderMapEntriesByKeys() && !(values instanceof SortedMap<?, ?>) ) {
Expand All @@ -98,6 +104,5 @@ public void doSerialize( JsonWriter writer, @Nonnull M values, JsonSerialization

}
}
writer.endObject();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import com.github.nmorel.gwtjackson.rebind.bean.BeanProcessor;
import com.github.nmorel.gwtjackson.rebind.bean.BeanTypeInfo;
import com.github.nmorel.gwtjackson.rebind.exception.UnsupportedTypeException;
import com.github.nmorel.gwtjackson.rebind.property.PropertiesContainer;
import com.github.nmorel.gwtjackson.rebind.property.PropertyInfo;
import com.github.nmorel.gwtjackson.rebind.property.processor.PropertyProcessor;
import com.github.nmorel.gwtjackson.rebind.type.JDeserializerType;
Expand Down Expand Up @@ -165,13 +166,13 @@ public String create( JClassType beanType ) throws UnableToCompleteException, Un
// retrieve the informations on the beans and its properties
BeanInfo beanInfo = BeanProcessor.processBean( logger, typeOracle, configuration, beanType );

ImmutableMap<String, PropertyInfo> properties = PropertyProcessor
PropertiesContainer properties = PropertyProcessor
.findAllProperties( configuration, logger, typeOracle, beanInfo, samePackage );

beanInfo = BeanProcessor.processProperties( configuration, logger, typeOracle, beanInfo, properties );

mapperInfo = new BeanJsonMapperInfo( beanType, qualifiedSerializerClassName, simpleSerializerClassName,
qualifiedDeserializerClassName, simpleDeserializerClassName, beanInfo, properties );
qualifiedDeserializerClassName, simpleDeserializerClassName, beanInfo, properties.getProperties() );

typeOracle.addBeanJsonMapperInfo( beanType, mapperInfo );
}
Expand Down
Loading

0 comments on commit 4ae5919

Please sign in to comment.