jackson-dataformats-binary
jackson-dataformats-binary copied to clipboard
[cbor] Consider adding support for custom tag handling
It would be nice if there were some programming interface allowing for custom tag-to-type mapping. For instance:
CborTag customTag = CborTag.fromInt(customTagValue);
CborTagDeserializer<CustomType> customTagDeserializer = new CborTagDeserializer<>() { ... };
CBORFactory cborFactory = new CBORFactory();
cborFactory.addTagDeserializer(customTag, customTagDeserializer);
ObjectMapper mapper = new ObjectMapper(cborFactory);
SomeType object = mapper.readValue(cborData, SomeType.class);
CborTagDeserializer might be defined as such:
public interface CborTagDeserializer<T>
{
T deserializeTaggedData(byte[] taggedData);
}
Likewise, there should be a way to handle serialization:
public interface CborTagSerializer<T>
{
byte[] serializeTaggedType(T value);
}
CborTagSerializer<CustomType> customTagSerializer = new CborTagSerializer<>() { ... };
cborFactory.addTagSerializer(customTag, customTagSerializer);
cborFactory.addTaggedTypeMapping(SomeType.class, customTag);
Are there any plans to add support for such a feature?
Thanks.
This may be difficult to make work reliably, since databinding can not have format-specific handling, and streaming parser (CBORParser) has to expose all data using standard JsonToken types.
But there may be ways to expose some of scalar types as JsonToken.VALUE_EMBEDDED_OBJECT: things like java.util.UUID and possibly timestamp-based date/time types.
Jackson 2.9 also allows some level of support for format-customizable polymorphic type ids (that is, generator may choose format-specific embedding method). That may not help here, since this does not seem to be about polymorphism, but I mention it for sake of completeness.
What would help here would be actual concrete use case, of problem being solved. I understand concept of tagging for format, but what matters more is the conceptual end-to-end usage: what kinds of datatypes were to be to supported.
The primary use case would be for tagged byte strings, which contain application-defined binary data of arbitrary structure.
At the very least, CBOR encoding/decoding should support an option such as "USE_TAGGED_BYTE_STRINGS" which instead of serializing/deserializing with byte[] would instead produce or consume something like this:
public class TaggedBytes
{
public int tag;
public byte[] data;
}
Then conversion to/from custom defined Java types could at least be done at the application level.
Since tag id is available via CBORParser, I think it should be possible and perhaps easy to write custom JsonDeserializer implementation that can read byte[] from event as well as access tag id.
Conversely I don't think I see this as something that should be supported by jackson core API as suggested. But I will keep it in mind in case it might evolve into something -- for example, it is quite possible that some sort of generic numeric "type id" could perhaps be exposed, since some formats do use similar concepts (Avro, for example, as union type identifier).
But even if that was added, on short term I would recommend considering custom deserializer route: it should be possible to create reusable and relatively generic way to plug that in.
Regarding #230, Date type is not supported for now.
I search if this is possible to use a more low level API using Tag.
I see this is possible to serialize data using Tag with CBORGenerator.writeTag(int), correct ?
But does it exist a way to deserialize data which are using Tag ?
@sbernard31 CBORParser does have method getCurrentTag() so custom deserializer could work, but there is no automated support for general databinding.
Currently I'm rather using JsonNode API like JsonNode node = mapper.readTree(cbor);
If I well understand if I need tag support I need to move to usage of JsonDeserializer ? (it sounds less straightforward :thinking:)
Could we imaging that in the future we could have a default CborDeserializer which create CborNode instead of JsonNode and so on this node we could have more CBOR specific method like node.getTag() ?
(I'm not sure all of this makes sense ?)
Right, unfortunately use of JsonNode is not going to be easy as things are. There was an idea originally to allow customized alternative trees (from ObjectMapper perspective) but things get quite difficult pretty quickly. What does exist is JsonNodeFactory, ability to create your own type hierarchy (sub-classing, most likely); you could possibly try that.
I don't see a near-term likelihood of CBOR-specific nodes, although same challenges exist for, say, XML and YAML. But maybe something that could be built... I will keep this issue in mind.
But you may want to have a look at how to create JsonNodeFactory, see if you could use sub-classing to do something.