FasterXML/jackson-modules-base

GuiceInjectableValues doesn't seem to work correctly

Opened this issue · 2 comments

Looking at the code of GuiceInjectableValues, it seems unable to handle string values, which is what you get by default:

  @Override
  public Object findInjectableValue(
      Object valueId, DeserializationContext ctxt, BeanProperty forProperty, Object beanInstance
  )
  {
    return injector.getInstance((Key<?>) valueId);
  }

We try to deserialize an object of class A:

package org.example;

import com.fasterxml.jackson.annotation.*;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;

public class A
{
   private final String name;

   @Inject
   @JsonCreator
   A(@JacksonInject X x, @Assisted @JsonProperty("name") String name) {
       this.name = name;
   }

   public String getName() {
       return name;
   }
}

But valueId, in findInjectableValue, takes the name of the class, which is a string and cannot be converted to a Key, and we get an ClassCastException.

We ended-up creating our own InjectableValues subclass to handle this correctly:

package org.example;

import com.fasterxml.jackson.databind.*;
import com.google.inject.*;

public class WorkingGuiceInjectableValues extends InjectableValues
{
    private final Injector injector;

    public WorkingGuiceInjectableValues(Injector injector) {
        this.injector = injector;
    }

    public Object findInjectableValue(Object valueId, DeserializationContext ctxt, BeanProperty forProperty, Object beanInstance) {
        try
        {
            return this.injector.getInstance(WorkingGuiceInjectableValues.class.getClassLoader().loadClass((String)valueId));
        }
        catch (ClassNotFoundException e)
        {
            throw new RuntimeException(e);
        }
    }
}

This is what the main of our small toy program looks like:

package org.example;

import java.io.*;

import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.module.guice.*;
import com.google.inject.Guice;

public class Main
{
    public static void main(String[] args) throws IOException
    {
        System.err.println("hello world");
        var objectMapper = new ObjectMapper();
        var injector = Guice.createInjector(new ObjectMapperModule(), new InjectionModule());
        var aFactory = injector.getInstance(AFactory.class);
        var a = aFactory.create("New instance of org.example.A !!!");
        System.err.println("a name: " + a.getName());
        var file = new File("a.json");
        objectMapper.writer().writeValue(file, a);
        var a2 = objectMapper.reader(new GuiceInjectableValues(injector)).readValue(file, A.class);
        System.err.println("a2 name: " + a2.getName());
    }
}

Version of guice: 5.1.0
Version of jackson-module-guice: 2.13.3

Program is available on GitHub: https://github.com/plcarmel/jackson-test

I don't know if the original author of this module is around any more, but if you were able to provide a PR against 2.14 I could merge improvements. I don't know how practical this would be wrt compatibility but if you think it is doable I always try to help get PRs merged.