0

Using Jackson, how can I have JSON serialized/deserialized by one application using one set of classes, but have another application deserialize the same JSON and load different implementations of those classes?

I have a (Spring MVC) web application that allows users to define steps in a script, that in turn will be executed in a client application. Steps might be things like ShowDialogStep, with properties like dialogText, or WaitStep with a property of duration.

The client application will load collections of steps from the server. However, the classes instantiated by the client need to have execution-specific functionality like execute(), which in the case of WaitStep will keep a track of how far through waiting it is. Clearly the server-side application never needs know about this, and in less trivial examples the execute/update logic of a steps involves all manner of client-specific dependencies.

So, to recap I need:

  • The server application to map the 'prototype' classes to JSON;
  • The client application to read the same JSON but instantiate execution-specific classes instead of the 'prototype' ones.

Would this be something that could be configured on the client-side mapper, perhaps if the JSON was serialized using relative class names (rather than fully-qualified) then the deserializer could be configured to look in a different package for the implementations with execution logic in them?

DeejUK
  • 12,891
  • 19
  • 89
  • 169

1 Answers1

3

You can use this approach:

On the server side:

@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, 
      include=JsonTypeInfo.As.PROPERTY, property="@type")
class Prototype {
...
}

objectMapper.registerSubtypes(
            new NamedType(Prototype.class, "Execution"),
            ...
);

then it will serialize a Prototype instance and add a type of bean:

{
  "@type" : "Execution",
  ...
}

on the client-side:

@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, 
      include=JsonTypeInfo.As.PROPERTY, property="@type")
class Execution {
...
}

objectMapper.registerSubtypes(
            new NamedType(Execution.class, "Execution"), // the same name
    ....
);
objectMapper.readValue(....); // will be deserialized to an Execution instance
Eugene Retunsky
  • 13,009
  • 4
  • 52
  • 55