下面列出了怎么用com.fasterxml.jackson.annotation.JsonTypeInfo.As的API类实例代码及写法,或者点击链接到github查看源代码。
/**
* value 值 序列化
*
* @return RedisSerializer
*/
@Bean
@ConditionalOnMissingBean(RedisSerializer.class)
public RedisSerializer<Object> redisSerializer(MicaRedisProperties properties,
ObjectProvider<ObjectMapper> objectProvider) {
MicaRedisProperties.SerializerType serializerType = properties.getSerializerType();
if (MicaRedisProperties.SerializerType.JDK == serializerType) {
return new JdkSerializationRedisSerializer();
}
// jackson findAndRegisterModules,use copy
ObjectMapper objectMapper = objectProvider.getIfAvailable(ObjectMapper::new).copy();
// findAndRegisterModules
objectMapper.findAndRegisterModules();
// class type info to json
GenericJackson2JsonRedisSerializer.registerNullValueSerializer(objectMapper, null);
objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(), DefaultTyping.NON_FINAL, As.PROPERTY);
return new GenericJackson2JsonRedisSerializer(objectMapper);
}
/**
* Helper method called to ensure that we do not have "duplicate" type ids.
* Added to resolve [databind#222]
*
* @since 2.6
*/
protected List<BeanPropertyWriter> removeOverlappingTypeIds(SerializerProvider prov,
BeanDescription beanDesc, BeanSerializerBuilder builder,
List<BeanPropertyWriter> props)
{
for (int i = 0, end = props.size(); i < end; ++i) {
BeanPropertyWriter bpw = props.get(i);
TypeSerializer td = bpw.getTypeSerializer();
if ((td == null) || (td.getTypeInclusion() != As.EXTERNAL_PROPERTY)) {
continue;
}
String n = td.getPropertyName();
PropertyName typePropName = PropertyName.construct(n);
for (BeanPropertyWriter w2 : props) {
if ((w2 != bpw) && w2.wouldConflictWithName(typePropName)) {
bpw.assignTypeSerializer(null);
break;
}
}
}
return props;
}
/**
* Helper method called to ensure that we do not have "duplicate" type ids.
* Added to resolve [databind#222]
*
* @since 2.6
*/
protected List<BeanPropertyWriter> removeOverlappingTypeIds(SerializerProvider prov,
BeanDescription beanDesc, BeanSerializerBuilder builder,
List<BeanPropertyWriter> props)
{
for (int i = 0, end = props.size(); i < end; ++i) {
BeanPropertyWriter bpw = props.get(i);
TypeSerializer td = bpw.getTypeSerializer();
if ((td == null) || (td.getTypeInclusion() != As.EXTERNAL_PROPERTY)) {
continue;
}
String n = td.getPropertyName();
PropertyName typePropName = PropertyName.construct(n);
for (BeanPropertyWriter w2 : props) {
if ((w2 != bpw) && w2.wouldConflictWithName(typePropName)) {
bpw.assignTypeSerializer(null);
break;
}
}
}
return props;
}
/**
* json序列化
*
* @return
*/
@Bean
public RedisSerializer<Object> jackson2JsonRedisSerializer() {
//使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
// 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
objectMapper.setVisibility(PropertyAccessor.ALL, Visibility.ANY);
// 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
//objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL, As.WRAPPER_ARRAY);
serializer.setObjectMapper(objectMapper);
return serializer;
}
/**
* Build the code to initialize a {@link TypeSerializationInfo} or {@link TypeDeserializationInfo}.
*
* @param typeInfo the type information obtained through the {@link JsonTypeInfo} annotation
* @return the code built
*/
protected final CodeBlock generateTypeInfo( BeanTypeInfo typeInfo ) {
Class type;
ImmutableMap<JClassType, String> mapTypeToMetadata;
if ( isSerializer() ) {
type = TypeSerializationInfo.class;
mapTypeToMetadata = typeInfo.getMapTypeToSerializationMetadata();
} else {
type = TypeDeserializationInfo.class;
mapTypeToMetadata = typeInfo.getMapTypeToDeserializationMetadata();
}
CodeBlock.Builder builder = CodeBlock.builder()
.add( "new $T($T.$L, $S)", type, As.class, typeInfo.getInclude(), typeInfo.getPropertyName() )
.indent()
.indent();
for ( Entry<JClassType, String> entry : mapTypeToMetadata.entrySet() ) {
builder.add( "\n.addTypeInfo($T.class, $S)", rawName( entry.getKey() ), entry.getValue() );
}
return builder.unindent().unindent().build();
}
/**
* Process the properties of the bean to find additionnal informations like @JsonValue.
*
* @param configuration the configuration
* @param logger the logger
* @param typeOracle the oracle
* @param beanInfo the previous bean information
* @param properties the properties of the bean
* @return the new informations about the bean and its properties
*/
public static BeanInfo processProperties( RebindConfiguration configuration, TreeLogger logger, JacksonTypeOracle typeOracle,
BeanInfo beanInfo, PropertiesContainer properties ) {
if ( !properties.getValuePropertyInfo().isPresent() && !properties.getAnyGetterPropertyInfo().isPresent() && !properties
.getAnySetterPropertyInfo().isPresent() ) {
return beanInfo;
}
BeanInfoBuilder builder = new BeanInfoBuilder( beanInfo );
builder.setValuePropertyInfo( properties.getValuePropertyInfo() );
if ( properties.getValuePropertyInfo().isPresent() && beanInfo.getTypeInfo().isPresent() && As.PROPERTY.equals( beanInfo
.getTypeInfo().get().getInclude() ) ) {
// if the bean has type info on property with @JsonValue, we change it to WRAPPER_ARRAY because the value may not be an object
BeanTypeInfo typeInfo = beanInfo.getTypeInfo().get();
builder.setTypeInfo( Optional.of( new BeanTypeInfo( typeInfo.getUse(), As.WRAPPER_ARRAY, typeInfo
.getPropertyName(), typeInfo.getMapTypeToSerializationMetadata(), typeInfo.getMapTypeToDeserializationMetadata() ) ) );
}
builder.setAnyGetterPropertyInfo( properties.getAnyGetterPropertyInfo() );
builder.setAnySetterPropertyInfo( properties.getAnySetterPropertyInfo() );
return builder.build();
}
private void handleJsonTypeInfo(Type responseClassType, Map<String, Model> modelMap) {
if (responseClassType instanceof ParameterizedType) {
Type[] actualTypes = ((ParameterizedType) responseClassType).getActualTypeArguments();
for (Type type : actualTypes) {
handleJsonTypeInfo(type, modelMap);
}
} else if (responseClassType instanceof Class<?>){
Class<?> responseClass = ((Class<?>) responseClassType);
if (responseClass.isArray()) {
responseClass = responseClass.getComponentType();
}
JsonTypeInfo typeInfo = responseClass.getAnnotation(JsonTypeInfo.class);
if (typeInfo == null || StringUtils.isEmpty(typeInfo.property()) || typeInfo.include().equals(As.EXISTING_PROPERTY)) {
return;
}
Map<String, Property> properties = modelMap.get(responseClass.getSimpleName()).getProperties();
if (properties != null && !properties.containsKey(typeInfo.property())) {
properties.put(typeInfo.property(), new StringProperty());
}
}
}
/**
* Build the code to initialize a {@link TypeSerializationInfo} or {@link TypeDeserializationInfo}.
*
* @return the code built
*/
protected final CodeBlock generateTypeInfo() {
final Class<?> type = getMapperType();
CodeBlock.Builder builder = CodeBlock.builder()
.add("new $T($T.$L, $S)", type, As.class, subTypesInfo.getInclude(), subTypesInfo.getPropertyName())
.indent()
.indent();
for (Map.Entry<String, TypeMirror> entry : subTypesInfo.getSubTypes().entrySet()) {
builder.add("\n.addTypeInfo($T.class, $S)", entry.getValue(), entry.getKey());
}
return builder.unindent().unindent().build();
}
/**
* @since 2.8
*/
public AsPropertyTypeDeserializer(JavaType bt, TypeIdResolver idRes,
String typePropertyName, boolean typeIdVisible, JavaType defaultImpl,
As inclusion)
{
super(bt, idRes, typePropertyName, typeIdVisible, defaultImpl);
_inclusion = inclusion;
}
@Test
public void testSerialWithTypeList() throws Exception{
JsonMapper jsonMapper = JsonMapper.ignoreNull();
ObjectMapper mapper = jsonMapper.getObjectMapper();
mapper.enableDefaultTyping(DefaultTyping.NON_FINAL, As.PROPERTY);
List<StoreDetailVo> list = Lists.newArrayList();
StoreDetailVo storeDetailVo = new StoreDetailVo();
storeDetailVo.setStoreId(1L);
list.add(storeDetailVo);
String s = mapper.writeValueAsString(list);
System.out.println(s);
byte[] bytes = jsonMapper.toJsonBytes(list);
List<StoreDetailVo> list2 = jsonMapper.fromJson(bytes, new TypeReference<List<StoreDetailVo>>() {
});
assertThat(list2).isEqualTo(list2);
String str1 = LangUtils.newString(bytes);
System.out.println("json str1: " + str1);
TestJsonData u1 = new TestJsonData();
u1.setCreate_time(new Timestamp(new Date().getTime()));
u1.setUser_name("user_name");
String str = jsonMapper.toJson(u1);
System.out.println("json str: " + str);
bytes = jsonMapper.toJsonBytes(u1);
String str2 = LangUtils.newString(bytes);
System.out.println("json str2: " + str2);
/*Map jsonstr = jsonMapper.fromJson(bytes, Map.class);
System.out.println("json map: " + jsonstr);*/
}
@Test
public void testSerialWithTypeList() throws Exception{
JacksonXmlMapper jacksonXmlMapper = JacksonXmlMapper.ignoreNull();
ObjectMapper mapper = jacksonXmlMapper.getObjectMapper();
mapper.enableDefaultTyping(DefaultTyping.NON_FINAL, As.PROPERTY);
List<StoreDetailVo> list = Lists.newArrayList();
StoreDetailVo storeDetailVo = new StoreDetailVo();
storeDetailVo.setStoreId(1L);
list.add(storeDetailVo);
String s = mapper.writeValueAsString(list);
System.out.println(s);
}
public JsonRedisTemplate() {
JsonMapper jsonMapper = JsonMapper.ignoreNull();
ObjectMapper mapper = jsonMapper.getObjectMapper();
mapper.enableDefaultTyping(DefaultTyping.NON_FINAL, As.PROPERTY);//用这个配置,如果写入的对象是list,并且元素是复合对象时,会抛错:Current context not Object but Array
// mapper.enableDefaultTyping(DefaultTyping.JAVA_LANG_OBJECT);
// RedisSerializer<String> keySerializer = new StringRedisSerializer();
RedisSerializer<Object> keySerializer = new GenericJackson2JsonRedisSerializer(mapper);
RedisSerializer<Object> valueSerializer = new GenericJackson2JsonRedisSerializer(mapper);
setKeySerializer(keySerializer);
setValueSerializer(valueSerializer);
setHashKeySerializer(keySerializer);
setHashValueSerializer(valueSerializer);
}
static public RedisSerializer<Object> typingJackson2RedisSerializer() {
JsonMapper jsonMapper = JsonMapper.ignoreNull();
ObjectMapper mapper = jsonMapper.getObjectMapper();
mapper.enableDefaultTyping(DefaultTyping.NON_FINAL, As.PROPERTY);//用这个配置,如果写入的对象是list,并且元素是复合对象时,会抛错:Current context not Object but Array
// mapper.enableDefaultTyping(DefaultTyping.JAVA_LANG_OBJECT);
RedisSerializer<Object> valueSerializer = new GenericJackson2JsonRedisSerializer(mapper);
return valueSerializer;
}
public JsonObjectMapper() {
registerModule(module);
configure(MapperFeature.REQUIRE_SETTERS_FOR_GETTERS, true);
configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
enableDefaultTyping(DefaultTyping.NON_FINAL, As.WRAPPER_OBJECT);
typer = new ClassAliasTypeResolverBuilder(DefaultTyping.NON_FINAL);
setDefaultTyping(typer.inclusion(As.WRAPPER_OBJECT));
}
/**
* <p>processType</p>
*
* @param logger a {@link com.google.gwt.core.ext.TreeLogger} object.
* @param typeOracle a {@link com.github.nmorel.gwtjackson.rebind.JacksonTypeOracle} object.
* @param configuration a {@link com.github.nmorel.gwtjackson.rebind.RebindConfiguration} object.
* @param typeOracle a {@link com.github.nmorel.gwtjackson.rebind.JacksonTypeOracle} object.
* @param type a {@link com.google.gwt.core.ext.typeinfo.JClassType} object.
* @param jsonTypeInfo a {@link com.google.gwt.thirdparty.guava.common.base.Optional} object.
* @param propertySubTypes a {@link com.google.gwt.thirdparty.guava.common.base.Optional} object.
* @return a {@link com.google.gwt.thirdparty.guava.common.base.Optional} object.
* @throws com.google.gwt.core.ext.UnableToCompleteException if any.
*/
public static Optional<BeanTypeInfo> processType( TreeLogger logger, JacksonTypeOracle typeOracle, RebindConfiguration configuration,
JClassType type, Optional<JsonTypeInfo> jsonTypeInfo, Optional<JsonSubTypes>
propertySubTypes ) throws UnableToCompleteException {
if ( !jsonTypeInfo.isPresent() ) {
jsonTypeInfo = findFirstEncounteredAnnotationsOnAllHierarchy( configuration, type, JsonTypeInfo.class );
if ( !jsonTypeInfo.isPresent() ) {
return Optional.absent();
}
}
Id use = jsonTypeInfo.get().use();
As include = jsonTypeInfo.get().include();
String propertyName = jsonTypeInfo.get().property().isEmpty() ? jsonTypeInfo.get().use().getDefaultPropertyName() : jsonTypeInfo
.get().property();
Optional<JsonSubTypes> typeSubTypes = findFirstEncounteredAnnotationsOnAllHierarchy( configuration, type, JsonSubTypes.class );
// TODO we could do better, we actually extract metadata twice for a lot of classes
ImmutableMap<JClassType, String> classToSerializationMetadata = extractMetadata( logger, configuration, type, jsonTypeInfo,
propertySubTypes, typeSubTypes, CreatorUtils
.filterSubtypesForSerialization( logger, configuration, type ) );
ImmutableMap<JClassType, String> classToDeserializationMetadata = extractMetadata( logger, configuration, type, jsonTypeInfo,
propertySubTypes, typeSubTypes, CreatorUtils
.filterSubtypesForDeserialization( logger, configuration, type ) );
return Optional.of(
new BeanTypeInfo( use, include, propertyName, classToSerializationMetadata, classToDeserializationMetadata ) );
}
BeanTypeInfo( Id use, As include, String propertyName, ImmutableMap<JClassType, String> mapTypeToSerializationMetadata,
ImmutableMap<JClassType, String> mapTypeToDeserializationMetadata ) {
this.use = use;
this.include = include;
this.propertyName = propertyName;
this.mapTypeToSerializationMetadata = mapTypeToSerializationMetadata;
this.mapTypeToDeserializationMetadata = mapTypeToDeserializationMetadata;
}
public GenericMsgpackRedisSerializer() {
this.mapper = new ObjectMapper(new MessagePackFactory());
this.mapper.registerModule((new SimpleModule()).addSerializer(new GenericMsgpackRedisSerializer.NullValueSerializer(null)));
this.mapper.enableDefaultTyping(DefaultTyping.NON_FINAL, As.PROPERTY);
}
/** {@inheritDoc} */
@Override
public T doDeserialize(JsonReader reader, JsonDeserializationContext ctx, JsonDeserializerParameters params) {
// Processing the parameters. We fallback to default if parameter is not present.
final IdentityDeserializationInfo identityInfo = null == params.getIdentityInfo() ? defaultIdentityInfo : params.getIdentityInfo();
final TypeDeserializationInfo typeInfo = null == params.getTypeInfo() ? defaultTypeInfo : params.getTypeInfo();
JsonToken token = reader.peek();
// If it's not a json object or array, it must be an identifier
if (null != identityInfo && !JsonToken.BEGIN_OBJECT.equals(token) && !JsonToken.BEGIN_ARRAY.equals(token)) {
Object id;
if (identityInfo.isProperty()) {
HasDeserializerAndParameters propertyDeserializer = deserializers.get(identityInfo.getPropertyName());
if (null == propertyDeserializer) {
propertyDeserializer = instanceBuilder.getParametersDeserializer().get(identityInfo.getPropertyName());
}
id = propertyDeserializer.getDeserializer().deserialize(reader, ctx);
} else {
id = identityInfo.readId(reader, ctx);
}
Object instance = ctx.getObjectWithId(identityInfo.newIdKey(id));
if (null == instance) {
throw ctx.traceError("Cannot find an object with id " + id, reader);
}
return (T) instance;
}
T result;
if (null != typeInfo) {
As include;
if (JsonToken.BEGIN_ARRAY.equals(token)) {
// we can have a wrapper array even if the user specified As.PROPERTY in some cases (enum, creator delegation)
include = As.WRAPPER_ARRAY;
} else {
include = typeInfo.getInclude();
}
switch (include) {
case PROPERTY:
// the type info is the first property of the object
reader.beginObject();
Map<String, String> bufferedProperties = null;
String typeInfoProperty = null;
while (JsonToken.NAME.equals(reader.peek())) {
String name = reader.nextName();
if (typeInfo.getPropertyName().equals(name)) {
typeInfoProperty = reader.nextString();
break;
} else {
if (null == bufferedProperties) {
bufferedProperties = new HashMap<String, String>();
}
bufferedProperties.put(name, reader.nextValue());
}
}
if (null == typeInfoProperty) {
throw ctx.traceError("Cannot find the property " + typeInfo
.getPropertyName() + " containing the type information", reader);
}
result = getDeserializer(reader, ctx, typeInfo, typeInfoProperty)
.deserializeInline(reader, ctx, params, identityInfo, typeInfo, typeInfoProperty, bufferedProperties);
reader.endObject();
break;
case WRAPPER_OBJECT:
// type info is included in a wrapper object that contains only one property. The name of this property is the type
// info and the value the object
reader.beginObject();
String typeInfoWrapObj = reader.nextName();
result = getDeserializer(reader, ctx, typeInfo, typeInfoWrapObj)
.deserializeWrapped(reader, ctx, params, identityInfo, typeInfo, typeInfoWrapObj);
reader.endObject();
break;
case WRAPPER_ARRAY:
// type info is included in a wrapper array that contains two elements. First one is the type
// info and the second one the object
reader.beginArray();
String typeInfoWrapArray = reader.nextString();
result = getDeserializer(reader, ctx, typeInfo, typeInfoWrapArray)
.deserializeWrapped(reader, ctx, params, identityInfo, typeInfo, typeInfoWrapArray);
reader.endArray();
break;
default:
throw ctx.traceError("JsonTypeInfo.As." + typeInfo.getInclude() + " is not supported", reader);
}
} else if (canDeserialize()) {
result = deserializeWrapped(reader, ctx, params, identityInfo, null, null);
} else {
throw ctx.traceError("Cannot instantiate the type " + getDeserializedType().getName(), reader);
}
return result;
}
public SubTypesInfo(As include, String propertyName, Map<String, TypeMirror> subTypes) {
this.include = include;
this.propertyName = propertyName;
this.subTypes = subTypes;
}
public As getInclude() {
return include;
}
/**
* @since 2.8
*/
public AsPropertyTypeDeserializer(JavaType bt, TypeIdResolver idRes,
String typePropertyName, boolean typeIdVisible, JavaType defaultImpl)
{
this(bt, idRes, typePropertyName, typeIdVisible, defaultImpl, As.PROPERTY);
}
@Override
public As getTypeInclusion() { return _inclusion; }
@Override
public As getTypeInclusion() { return As.WRAPPER_ARRAY; }
@Override
public As getTypeInclusion() { return As.WRAPPER_OBJECT; }
@Override
public As getTypeInclusion() { return As.WRAPPER_OBJECT; }
@Override
public As getTypeInclusion() { return As.PROPERTY; }
@Override
public As getTypeInclusion() { return As.EXISTING_PROPERTY; }
@Override
public As getTypeInclusion() { return As.WRAPPER_ARRAY; }
@Override
public As getTypeInclusion() { return As.EXTERNAL_PROPERTY; }
@Override
public As getTypeInclusion() { return As.EXTERNAL_PROPERTY; }