Search code examples
javaparsingjacksonyaml

YAML Jackson - Anchor keys of Array


I am trying to parse a YAML file into an object.

Even though Online YAML Parser tells me that it is parsable the way I want, Jackson YAML parser refuses to give me what I want.

Here is the YAML File :

- nom: "service1"
  etats : &e1s1
    - nom: "e1"
      childs:
        - nom: "e2"
          childs:
            - nom: "e3"
              childs:
              - &a
                nom: "e5"
        - nom: "e4"
          childs:
            - <<: *a

Online YAML Parser tells me that "e4" and "e3" have "e5" as a child.

However when I try to parse this with Jackson, I get the following error :

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "<<" (class Etat), not marked as ignorable (4 known properties: "dependsOnAnotherService", "nom", "hasToken", "childs"])
at [Source: (File); line: 13, column: 21] (through reference chain: java.lang.Object[][0]->Service["etats"]->java.util.ArrayList[0]->Etat["childs"]->java.util.ArrayList[1]->Etat["childs"]->java.util.ArrayList[0]->Etat["<<"])

So, I'd like to know if anybody have a way to do this where Jackson will accept it ?

Update

I also tried this :

- nom: "service1"
  etats : &e1s1
    - nom: "e1"
      childs:
        - nom: "e2"
          childs:
            - nom: "e3"
              childs:
              - &a
                nom: "e5"
        - nom: "e4"
          childs:
            - *a

But get :

com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `Etat` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('a')
at [Source: (File); line: 13, column: 15] (through reference chain: java.lang.Object[][0]->Service["etats"]->java.util.ArrayList[0]->Etat["childs"]->java.util.ArrayList[1]->Etat["childs"]->java.util.ArrayList[0])

Solution

  • << is not a core YAML feature and has only been specified as an optional tag to outdated YAML 1.1 (see here). Therefore, Jackson has every right not to support it. Instead, it tries to parse << as a field name, which obviously fails because there is no such field.

    Your second approach is more appropriate because it only uses core YAML features. The error you get is because Jackson is known not to support anchors and aliases and incorrectly treats the alias *a as a String instead of resolving it.

    Now you call Jackson a YAML parser in your question which it is not. It merely uses SnakeYaml as parser. SnakeYaml can load YAML to user-defined classes by itself, so you may be better of to directly use the SnakeYaml API. Afaik it handles aliases correctly.