All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.owlike.genson.convert.ClassMetadataConverter Maven / Gradle / Ivy

There is a newer version: 1.6
Show newest version
package com.owlike.genson.convert;

import java.io.IOException;
import java.lang.reflect.Type;

import com.owlike.genson.*;
import com.owlike.genson.annotation.HandleClassMetadata;
import com.owlike.genson.reflect.TypeUtil;
import com.owlike.genson.stream.ObjectReader;
import com.owlike.genson.stream.ObjectWriter;
import com.owlike.genson.stream.ValueType;

/**
 * Converter responsible of writing and reading @class metadata. This is useful if you want to be
 * able to deserialize all serialized objects without knowing their concrete type. Metadata is
 * written only in objects (never in arrays or literals) and is always the first element in the
 * object. Most default converters are annotated with @HandleClassMetada indicating that they will
 * not have class metadata written nor use it during deserialization. This feature is disabled by
 * default, to enable it use {@link com.owlike.genson.GensonBuilder#useClassMetadata(boolean)}.
 * Genson provides also a aliases mechanism that will replace the class name with the value of your alias
 * in the generated stream. You should use it as it is more "secure" and provides you more flexibility.
 * Indeed if you change the name or package of your class you will still be able to deserialize to it.
 * An example allowing to serialize a object and then deserialize it back without knowing its type would be:
 * 

*

 * class Foo {
 * }
 *
 * Genson genson = new GensonBuilder().useClassMetadata(true).addAlias("foo", Foo.class).create();
 * String json = genson.serialize(new Foo());
 * // json value will be {"@class":"Foo"}
 * Foo foo = (Foo) genson.deserialize(json, Object.class);
 * 
* * @param * @author eugen * @see com.owlike.genson.stream.ObjectWriter#writeMetadata(String, String) ObjectWriter.metadata(key, value) * @see com.owlike.genson.stream.ObjectReader#metadata(String) ObjectReader.metadata("class") * @see com.owlike.genson.Genson#aliasFor(Class) Genson.aliasFor(Class) */ public class ClassMetadataConverter extends Wrapper> implements Converter { public static class ClassMetadataConverterFactory extends ChainedFactory { @SuppressWarnings({"unchecked", "rawtypes"}) @Override protected Converter create(Type type, Genson genson, Converter nextConverter) { if (nextConverter == null) throw new IllegalArgumentException( "nextConverter must be not null for ClassMetadataConverter, " + "as ClassMetadataConverter can not be the last converter in the chain!"); Class rawClass = TypeUtil.getRawClass(type); if (genson.isWithClassMetadata() && !Wrapper.toAnnotatedElement(nextConverter).isAnnotationPresent( HandleClassMetadata.class)) return new ClassMetadataConverter(rawClass, nextConverter); else return nextConverter; } } private final Class tClass; public ClassMetadataConverter(Class tClass, Converter delegate) { super(delegate); this.tClass = tClass; } public void serialize(T obj, ObjectWriter writer, Context ctx) throws Exception { // obj != null allows to not fail in case when the NullConverter is not in the chain if (!Object.class.equals(tClass) && obj != null) { writer.beginNextObjectMetadata() .writeMetadata("class", ctx.genson.aliasFor(obj.getClass())); } wrapped.serialize(obj, writer, ctx); } public T deserialize(ObjectReader reader, Context ctx) throws Exception { if (ValueType.OBJECT.equals(reader.getValueType())) { String className = reader.nextObjectMetadata().metadata("class"); if (className != null) { try { Class classFromMetadata = ctx.genson.classFor(className); if (!classFromMetadata.equals(tClass)) { Converter deser = ctx.genson.provideConverter(classFromMetadata); return deser.deserialize(reader, ctx); } } catch (ClassNotFoundException e) { throw new JsonBindingException( "Could not use @class metadata, no such class: " + className); } } } return wrapped.deserialize(reader, ctx); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy