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 );
>    }
> }
> 

Reply via email to