I'm currently trying to use jackson-dataformat-cbor:2.19.0 and want to parse custom tags. Since I couldn't find specific examples, I attempted to implement it with the following code.

public class CborParserDelegate extends JsonParserDelegate {

    protected final CBORParser delegate;

    public CborParserDelegate(CBORParser d) {
        super(d);
        this.delegate = d;
    }

    @Override
    public CBORParser delegate() {
        return (CBORParser) super.delegate();
    }

    public int getCurrentTag() {
        return delegate().getCurrentTag();
    }

    public CBORParser.TagList getCurrentTags() {
        return delegate().getCurrentTags();
    }

}
public class CustomTagsCborParser extends CborParserDelegate {

    public CustomTagsCborParser(CBORParser d) {
        super(d);
        try {
            this.method = ParserMinimalBase.class.getDeclaredMethod("_updateToken", JsonToken.class);
            this.method.setAccessible(true);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private final Method method;
    private Object customValue;

    @Override
    public JsonToken nextToken() throws IOException {
        JsonToken jsonToken = super.nextToken();
        int currentTag = delegate.getCurrentTag();
        if (currentTag != -1) {
            ObjectCodec codec = getCodec();
            this.customValue = mapValue(currentTag, codec.readTree(delegate));
            return Err.call(() -> (JsonToken) method.invoke(delegate, JsonToken.VALUE_EMBEDDED_OBJECT));
        }
        return jsonToken;
    }


    @Override
    public Object getEmbeddedObject() throws IOException {
        if (this.customValue != null) {
            Object v = this.customValue;
            this.customValue = null;
            return v;
        }
        return super.getEmbeddedObject();
    }

    private Object mapValue(int tag, TreeNode treeNode) {
        CustomTag customTag = CustomTag.of(tag);
        switch (customTag) {
            case TAG_12: {
                _assert(treeNode.isArray(), "TAG_12 should be an array with two items.");
                ArrayNode arrayNode = (ArrayNode) treeNode;
                long seconds = arrayNode.get(0).asLong(0);
                long nanoSeconds = arrayNode.get(1).asLong(0);
                return Instant.ofEpochSecond(seconds, nanoSeconds);
            }
            case TAG_14: {
                _assert(treeNode.isArray(), "TAG_14 should be an array with two items.");
                ArrayNode arrayNode = (ArrayNode) treeNode;
                long seconds = arrayNode.at("/0").asLong(0);
                long nanoSeconds = arrayNode.at("/1").asLong(0);
                return Duration.ofSeconds(seconds, nanoSeconds);
            }
            default:
                return treeNode;
        }
    }

    private void _assert(boolean state, String message) {
        if (!state) {
            throw new IllegalStateException(message);
        }
    }

}

However, since CborParser inherits from ParserMinimalBase, calling its _updateToken(JsonToken) method requires reflection, which I'd like to avoid.

So my questions are:

  1. Is my approach for custom tag parsing with dataformat-cbor correct (or aligned with your design)? If not, what should I do instead?
  2. Is there a way to avoid using reflection when updating tokens?

Comment From: cowtowncoder

I think you have basically hit an unsupported use case, and I suspect your work-arounds are unfortunately required. _updateToken() is not designed to be accessible from outside class (or super-class.

Ideally I think there would be a pluggable extension point/handler of some kind to help with custom tags, but there isn't anything right now.

Comment From: honhimW

@cowtowncoder Well, it seems that for now, reflection is required.

BTW, although this question should probably be posted in the jackson-dataformats-binary. If it's convenient for you, could you let me know if there are any code repositories using jackson-cbor to handle custom tags that I could refer to? I've tried many searches but couldn't find any concrete examples, even though this should be a relatively common feature in CBOR.

Comment From: cowtowncoder

@honhimW I am not aware of other repositories doing that, you are the first one. You are probably right ones exists but I haven't been contacted by anyone else.

I will file a general issue for adding such extension point, as a discussion starter.

EDIT: https://github.com/FasterXML/jackson-dataformats-binary/issues/581