3

guys! I am developing a web application and I decided to use Jackson as my JSON processing framework.

In request data that I am willing to send; let's say the POJO looks like this:

data class JSONEnvelope(
        @JsonProperty("obj1")
        val obj1: Obj1,

        @JsonProperty("obj2")
        val obj2: Obj2)

which get serialized like this:

{
    "obj1":{...},
    "obj2":{...}
}

but I need to add some metadata to that object, let's say fields meta1 and meta. I thought that @JsonAppend would solve my problem, but I am using Jackson together with Jersey, so I am not serializing objects manually, so I cannot use writer.withAttribute("...", ...).

I am aware of this thread, but there is no answer that kinda satisfy my needs, because I think, that writing a custom serializer is a bit overkill for this, moreover if I do not have a mechanism to "serialize the rest of the original object". I'd be glad for any ideas

Maroš Šeleng
  • 1,600
  • 13
  • 28
  • In this context, what do you mean by "metadata"? Could it be implemented as simple computed properties that Jackson maps in the normal way? – Paul Hicks Aug 20 '17 at 21:53
  • @PaulHicks By metadata I mean additional fields, because this object is the root one and remote API requires to have, for example, the JSON version specified, so I'd like to add field `"jsonrpc":"2.0"`. Yes, I can add it as a field to the class, but I think that it does not belong there as that information is not the part of the entity's state. I don't know what you mean by computed properties – Maroš Šeleng Aug 20 '17 at 21:57
  • Computed properties are simply ones with no setter (or where the setter does nothing); for example, `val jsonrpc = "2.0"` or `var time = Date().getTime()`. Some properties would be suitable for an envelope class. If you don't to modify `JSONEnvelope`, then JsonAppend does seem like the best option. If you can't modify the ObjectWriter after calling `ObjectMapper.writerFor` then you'll have to do it beforehand, by overriding the `writerFor` method in an ObjectMapper that you provide using `@Provider`. – Paul Hicks Aug 20 '17 at 22:11
  • @PaulHicks Thank you for clearance! If you convert a comment to an answer, I'd be glad to accept it. I didn't even think about overriding `writeFor`, Thanks! – Maroš Šeleng Aug 21 '17 at 07:18

1 Answers1

1

The solution in the answer you cited, which adds a mixIn to a the ObjectMapper then uses the ObjectWriter to configure it, is a good solution.

For Jersey, which calls ObjectMapper.writerFor and therefore prevents you from calling withAttribute in order to configure the ObjectWriter, one alternative is to add the attribute to the ObjectWriter before returning it from writerFor. I suggest subclassing ObjectMapper and overriding the various writerFor methods, adding the necessary attribute at that point. You can then get Jersey to use that ObjectMapper by registering it as a JAX-RS Provider: see the various annotations in javax.ws.rs to get started on this. This answer gives an example of what to do.

Paul Hicks
  • 13,289
  • 5
  • 51
  • 78