2

We use Google Guice for DI (mostly with constructor injection) and Jackson for object serialization to/from JSON. As such we build our object graph through Guice Modules.

How do we provide/instruct Jackson to use our pre-built Guice Injector? Or it's own injector based on a Guice Module we provide? My preference is to provide it the injector because we already have means to control which module is used based on the environment/configuration we want to run in.

Here's a unit test:

public class Building {

    @JsonIgnore
    public final ElectricalProvider electricalProvider;

    public String name;

    @Inject
    Building(ElectricalProvider electricalProvider){
         this.electricalProvider = electricalProvider;
    }

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

}

public interface ElectricalProvider {}

public class SolarElectricalProvider implements  ElectricalProvider{}

@Test
public void testJacksonGuice() throws IOException {

    Injector injector = Guice.createInjector(new Module() {
      @Override public void configure(Binder binder) {
           binder.bind(ElectricalProvider.class).to(SolarElectricalProvider.class);
      }
    });

    Building building1 = injector.getInstance(Building.class);
    building1.setName("test building");

    ObjectMapper objectMapper = new ObjectMapper();

    byte[] buildingJsonBytes = objectMapper.writeValueAsBytes(building1);

    Building building2 = objectMapper.readValue(buildingJsonBytes, Building.class);

    assertThat(building1, is(equalTo(building2)));
    assertThat(building2.electricalProvider, is(instanceOf(SolarElectricalProvider.class)));

}

That when run generates this exception com.fasterxml.jackson.databind.JsonMappingException, with this message: No suitable constructor found for type [simple type, class Building]: can not instantiate from JSON object (missing default constructor or creator, or perhaps need to add/enable type information?)

After a bit of googling, I came across the jackson-module-guice project but it doesn't appear to be what we need or doesn't provide as to how to accomplish what we need to do.

peterl
  • 1,881
  • 4
  • 21
  • 34

1 Answers1

-1

Well, i think your approach is anti-pattern. You should serialize and deserialize only POJO object without any business logic and any further dependencies like services, repositories and so on. Could you show your Building class? What's in the constructor?

You should split your Building class into Service and Domain layers. The Service layer would use Domain and there you should inject all dependencies. The Domain layer would be only POJO bean with default constructor, no final fields and only getter/setter methods.

If you need to use final properties and constructor initialization you have few options as mentioned in Jackson 3rd Party Class With No Default Constructor

Community
  • 1
  • 1
Milan Baran
  • 4,133
  • 2
  • 32
  • 49
  • I disagree that I should split the logic as you suggest. One of the key aspects of object orientated design/development/programming is encapsulation of data and logic associated with the particular object into the object itself. – peterl Jun 05 '15 at 22:36
  • This doesn't answer the question. Would be best as a comment. – João Mendes Sep 06 '21 at 23:40