I had a few thoughts about this topic. In order to properly deserialise, we would need the schema. Since the DTO type *is* the schema, then somehow the schema needs to be serialised as well, or at least known upon serialisation.
If the API were to have a toSchema() method, that would simplify things a lot. A client should also be able to do something like this: SomeDTO dto = ... codec.encode( dto ).serializeTo( out ); Or maybe: codec.withSchema( SomeDTO.class).encode( dto ).to( out ); The SomeDTO schema would also be serialised (perhaps simply using the fully-qualified class name as an alias?), so then the client could do this: Object o = codec.deserializeFrom( in ) Since the schema is included in the input data, the serializer will behind the scene do something like: Map<String, Object> map = codec.decode( Map.class ).from( in ); // Get the schema type, which is SomeDTO.class ... Object o = converter.convert( map.get(“data”) ).to( SomeDTO.class ); wdyt? =David > On Aug 20, 2016, at 3:23 PM, David Leangen <[email protected]> wrote: > > > Hi, > > I am trying to use the Convert/Codec as a serializer, but it has been a bit > of a struggle so far. > > I have a “deep” object structure (i.e. at least one level of embedded > objects). Writing the data as a JSON string works just fine. However, when > deserialising, I am having trouble. The data object uses generics, so it is > not possible to determine the type at runtime. My embedded objects end up > being deserialised as Maps, which of course causes a ClassCastException later > on in the code. > > I have tried adding a Rule using an adapter, and setting the > codec.with(thatAdapter), but that didn’t work out so well, either. > > Here is an example of my attempt so far. I am working with Prevayler, so I > need to serialize/deserialze a command object, which contains some data. > > I think that this code _should_ work, which means that there is likely a bug > in the code. Even so… > > This is a very convoluted way of working, which doesn’t seem right to me. Am > I missing some concept? > > > Example below. > > Cheers, > =David > > > public class DTOSerializer<E> > implements Serializer // This is the interface provided by Prevayler > { > private final Converter converter; > private final Codec codec; > private final Class<E> type; > > public DTOSerializer( Converter aConverter, Codec aCodec, Class<E> aType ) > { > // Very convoluted attempt at adding a rule to try to make the > conversion of my “PutCommand” work during deserialization > converter = aConverter.getAdapter() > .rule( > PutCommand.class, > Map.class, > dto -> { Map map = new HashMap<>(); map.put( "key", > dto.key ); map.put( "entity", dto.entity ); return map; }, > map -> { PutCommand c = new PutCommand(); c.key = > (String)map.get( "key" ); c.entity = aConverter.convert( map.get( "entity" ) > ).to( aType ); return c; } ); > codec = aCodec.with( converter ); > } > > @Override > public Object readObject( InputStream in ) > throws Exception > { > // This is the raw data > final Map<String, Object> map = codec.decode( Map.class ).from( in ); > // The name of the object type to cast to > final String commandTypeName = (String)map.get( "command" ); > final Class<?> commandType = Class.forName( commandTypeName ); > // This indeed returns an object of the correct type, > // HOWEVER, the embedded objects are not of the correct type, they are > of type Map > final Object command = converter.convert( map.get( "payload" ) ).to( > commandType ); > return command; > } > > @Override > public void writeObject( OutputStream out, Object object ) > throws Exception > { > final Map<String, Object> map = new HashMap<>(); > // Serialize the name of the command so I know what to cast it do when > deserializing > map.put( "command", object.getClass().getName() ); > // This is the actual payload, which is nothing more than the command > object > map.put( "payload", object ); > codec.encode( map ).to( out ); > } > } >
