79178897

Date: 2024-11-11 19:33:47
Score: 1
Natty:
Report link

I have one half of an answer, and two full answers if you allow a frame challenge.

Half an answer

Load has a constructor that allows injecting your own factory into the deserialization process, and the functions where have access to Node objects that do carry the anchor.
So the approach would be something like this:

  Map<Object, ?> metadata = new HashMap<>();
  Load loader = new Load(
    settings,
    // Inject a StandardConstructor; BaseConstructor does not know about Map etc.
    new StandardConstructor(settings) {
      @Override
      protected Object constructObjectNoCheck(Node node) {
        // Let it construct the Pojo from the Node normally.
        final Object result = super.constructObjectNoCheck(node);
        // Now that you have both Pojo and internal Node,
        // you can exfiltrate whatever Node info that you want
        // and do metadata.put(result, someInfoGleanedFromNode)
        return result;
      }
    });

The snag is: The Node created for the anchor does not generate a Pojo.
I.e. you have an anchor, but you don't really know to which object in your deserialized nested Map/List that anchor corresponds; you'll likely have to walk the Node tree and find the correct node. So, maybe somebody else wants to add instructions how to walk the Node tree; I do not happen to know that.

Frame challenge: Do you really want the anchor name?

If this is just about error messages, each Node has a startMark attribute that's designed specifically for error messages that relate to the Node, so you can do this:

  Map<Object, String> startMarks = new HashMap<>();
  Load loader = new Load(
    settings,
      @Override
      protected Object constructObjectNoCheck(Node node) {
        final Object result = super.constructObjectNoCheck(node);
        node.getStartMark().ifPresent(mark -> startMarks.put(result, mark));
        return result;
      }
    });

e.g. for this YAML snippet:

servers:
  - &hetzner
    host: <REDACTED>
    username: <REDACTED>
    private_ssh_key: /home/<REDACTED>/.ssh/id_rsa

the servers label has this start mark:

 in config.yaml, line 1, column 1:
    servers:
    ^

To get this output, I initialized the settings like this:

var settings = LoadSettings.builder().setUseMarks(true).setLabel(path.toString()).build();

setUseMarks makes it generate start and end marks so you have these texts. setLabel is needed to give the in config.yaml output; otherwise, you'll see something like in reader (if you pass in a stream reader), which is pretty unhelpful.

Frame challenge: Maybe give the anchored subobject a name?

Something like this:

unit:
  &kg
  name: Kilogram
  shorthand: kg
Reasons:
  • Long answer (-1):
  • Has code block (-0.5):
  • Ends in question mark (2):
  • Low reputation (0.5):
Posted by: toolforger