Search code examples
jsonplayframework-2.1

How to indicate a specific Serializer for an object?


I have a model like :

SomeModel
    public Long id;
    public String name;
    public Integer age;
    public String address;
    public Profile profile;

In my templates, I'd like to render a simpler version of this model, only id and name.

If I do Json.toJson(SomeModel.find.findList()); it will render a list of the SomeModels in the database, but with the complete form.

I've written a Serializer that just returns id and name, but how can I tell Json.toJson to use this serializer ?

public class SimpleSomeModelSeralizer extends JsonSerializer<SomeModel> {
    @Override
    public void serialize(SomeModel someModel, JsonGenerator generator, SerializerProvider serializer) throws IOException,JsonProcessingException {
        if (someModel == null) return;

        generator.writeStartObject();

        generator.writeNumberField("id", someModel.getId());
        generator.writeStringField("name", someModel.getName());

        generator.writeEndObject();
    }

}

I've looked at the code in Play, and of course, toJson is a simple version, that doesn't take some serializer as parameter, so I guess I have to write a longer code, but I don't know what/how to do it.

Code in Play of Json.toJson :

public static JsonNode toJson(final Object data) {
    try {
        return new ObjectMapper().valueToTree(data);
    } catch(Exception e) {
        throw new RuntimeException(e);
    }
}

Is it possible to do something like this? :

new ObjectMapper().useSerializer(SimpleSomeModelSeralizer.class).valueToTree(SomeModel.find.findList());

Solution

  • Ok so, here's what I did. On the SomeModel class, I added a static method that returns the list as JsonNode, and I simply call it from my templates :

    public static JsonNode findItemsAsJson() {
        ObjectMapper mapper = new ObjectMapper();
        SimpleModule someModelModule = new SimpleModule("SomeModel", new Version(1, 0, 0, null));
        someModelModule.addSerializer(SomeModel.class, new SimpleSomeModelSeralizer());
        mapper.registerModule(someModelModule);
    
        return mapper.valueToTree(SomeModel.find.findList());
    }
    

    The drawback of this method is that you are bound to the query hard coded (SomeModel.find.findList()) but you can easily add a parameter to that method that is the query :

    public static JsonNode findItemsAsJson(Query<SomeModel> query) {
        ObjectMapper mapper = new ObjectMapper();
        SimpleModule someModelModule = new SimpleModule("SomeModel", new Version(1, 0, 0, null));
        someModelModule.addSerializer(SomeModel.class, new SimpleSomeModelSeralizer());
        mapper.registerModule(someModelModule);
    
        return mapper.valueToTree(query.findList());
    }
    

    And you call it with :

    SomeModel.findItemsAsJson(SomeModel.find.like("name", "B%").query());
    

    Hope it'll helps :)