Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jackson - Pass Values to JsonDeserializer

Tags:

java

json

jackson

I have an existing class hierarchy that looks like this:

public interface Service {
  String getId();
  String getName();
}

public class FooTask extends AbstractTask {
  private final static ObjectMapper JSON_MAPPER = new ObjectMapper();

  static {
    JSON_MAPPER.registerModule(new SimpleModule().addDeserializer(Result.class, new ResultDeserializer());
  }

  public FooTask(Service service) {
    super(service);
  }

  @Override public Result call() throws Exception {
     InputStream json = <... execute some code to retrieve JSON ...>
     Result result = JSON_MAPPER.readValue(json, Result.class);
  }

  private static class ResultDeserializer {
    @Override public Result deserialize(JsonParser parser, DeserializationContext ctx) throws IOException {

      //
      // Need to access service#getId() down here... but we're in a static nested class 
      // and I don't know how to access it. Is there some way to pass that info via the DeserializationContext?
      //

      <... Deserialization logic ...>
    }
  }
}

I need to pass some information to the deserializer at deserialization time but I cannot find a way to pass some contextual information to the deserializer at deserialization time. Is this possible? If so, how? I would prefer to not have to allocate a new ObjectMapper every time the FooTask is instantiated or #call() method is invoked.

like image 410
Philip Lombardi Avatar asked Feb 11 '23 14:02

Philip Lombardi


1 Answers

So I came up with a solution... no idea if it is the ideal solution, but it is a solution - basically I first create an instance of InjectableValues:

private InjectableValues newInjectableValues() {
  return new InjectableValues.Std()
    .addValue("providerId", service.getId())
}

Then I get a new ObjectReader instance from the ObjectMapper and use that to perform the deserialization:

JSON_MAPPER.reader(newInjectableValues()).withType(Result.class).readValue(inputStream)

Down in the actual Deserializer I use this method to retrieve the values provided by the InjectableValues:

ctx.findInjectableValue("providerId", null, null);
like image 184
Philip Lombardi Avatar answered Feb 15 '23 11:02

Philip Lombardi