ObjectMapper has to call Constructor with Arguments not provided by JSON file

derM :

My goal is to write some kind of bridge between our global event broker and Spring's ApplicationEvent system.

The message broker provides the messages in JSON format. My idea is to have an

public class ExternalApplicationEvent extends ApplicationEvent {
   ...
   // e.g @JsonPropert private String name;
}

And then call something like

objectMapper.readValue(brokerMessage, ExternalApplicationEvent.class);

The problem is, that the ApplicationEvent requires a source set on construction time, which should be the instance of the ExternalEventBridge, which is for obvious reasons not part of the JSON-document.

I found, how I can add properties to the JSON, that are not part of the serialized object with @JsonAppend, but I haven't found a solution for my direction, passing parameters to the constructor of the class.

My last idea was to use

objectMapper.readerForUpdating(new ExternalApplicationEvent(theSource)).readValue(message)

but somehow this didn't fill my event.

If I add the constructor

public ExternalApplicationEvent() {
  super(new Object());
}

and use objectMapper.readValue(message, ExternalApplicationEvent.class), the object is properly populated via field injection. Also adding Setters won't help.

derM :

I solved it now, by seperating the Data from the ApplicationEvent like this:

@JsonIgnoreProperties(ignoreUnknown = true)
@JsonAutoDetect(getterVisibility = JsonAutoDetect.Visibility.NONE) // Don't detect `getSource` from ApplicationEvent
public class ExternalApplicationEvent extends ApplicationEvent {

    // I might use @JsonUnwrapped probably, but since I have to create setters
    // and getters anyway...
    private ExternalApplicationEventData p = new ExternalApplicationEventData();

    public ExternalApplicationEvent(Object source, ExternalApplicationEventData data) {
        super(source);
        p = data;
    }

    @JsonGetter("name")
    public String getName() { return p.name; }

    public void setName(String name) { p.name = name; }

    public static class ExternalApplicationEventData {

        @JsonCreator
        private ExternalApplicationEventData() {} // Make creation only possible by parsing or from the ExternalApplicationEvent class

        @JsonProperty
        private String name;

        ...
    }
}

And then creating the Event

var data = objectMapper.readValue(message, ExternalApplicationEvent.ExternalApplicationEventData.class);
var event = new ExternalApplicationEvent(this, data);

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=163041&siteId=1
Recommended