On Tue, Feb 12, 2019 at 1:18 PM John Passaro <[email protected]> wrote:
>
> Hello folks! I am trying to deserialize a yaml file with anchors and 
> references. There are some existing StackOverflow questions along these lines 
> but the answers aren't quite getting me to the finish line.
>
> Here is my model:
>
> @JsonIdentityInfo(generator = ObjectIdGenerators.None.class)
> class YamlScratch {
>     @JsonProperty("misc")
>     List<List<String>> misc;
>
>     @JsonProperty("contents")
>     Map<String, Config> contents;
>
>     static class Config {
>         @JsonProperty("header")
>         String header;
>
>         @JsonProperty("labels")
>         @JsonIdentityInfo(generator = ObjectIdGenerators.None.class)
>         List<String> labels;
>     }
> }
>
>
>
> Here is my YAML:
>
> misc:
>   - &letters
>     - Aie
>     - Bee
>     - See
>   - &numbers
>     - One
>     - Two
>     - Three
>
> contents:
>   letters:
>     header: "This is a list of phonetic letters"
>     labels: *letters
>   numbers:
>     header: "This is a list of number spellings"
>     labels: *numbers
>   moreletters:
>     header: "this is another copy of the letters"
>     labels: *letters
>
>
> The idea is that I have lists that may be referenced more than once in the 
> "contents" tree, and I'd like to be able to reference them concisely.
>
> I've tried to enable this in my Java code by adding @JsonIdentityInfo to the 
> "labels" field that will reference these lists. As for the YAML, I added 
> "&..." anchors to the data that will be referenced, and where it should 
> appear I added "*..." references. PyYAML seems to confirm this is the correct 
> YAML usage:
>
> $ python3
> >>> import yaml
> >>> f = 
> >>> open("/Users/johnpassaro/Library/Preferences/IdeaIC2018.3/scratches/scratch.yml")
> >>> y = yaml.load(f)
> >>> y
> {'misc': [['Aie', 'Bee', 'See'], ['One', 'Two', 'Three']], 'contents': 
> {'letters': {'header': 'This is a list of phonetic letters', 'labels': 
> ['Aie', 'Bee', 'See']}, 'numbers': {'header': 'This is a list of number 
> spellings', 'labels': ['One', 'Two', 'Three']}}}
>
>
> With Jackson (2.9), I get an error:
>
> Exception in thread "main" 
> com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot 
> deserialize instance of java.util.ArrayList out of VALUE_STRING token
>  at [Source: (File); line: 14, column: 13] (through reference chain: 
> YamlScratch["contents"]->java.util.LinkedHashMap["letters"]->YamlScratch$Config["labels"])
>
> I tried changing
> List<String> labels;
> to
> Object labels;
> just to see how Jackson was treating it: instead of resolving the anchor 
> reference ("*letters"), it just returns the reference name as as a string 
> ("letters").
>
> One of the StackOverflow questions has an answer that mentions the feature 
> YAMLParser.Feature.USE_NATIVE_OBJECT_ID. That would seem to be exactly what I 
> need, but that enum value is not present in 2.9.
>
> Is this behavior supported at all? If so, what do I need to do to make it 
> work?
>
> Many thanks in advance for your help. I'd be happy to post the results on the 
> relevant SO threads to make sure this information get shared reasonably 
> widely.

Ok. I think I can point to the problem itself at least.

For Jackson to handle anchors and references, property value types (or
property declarations) need `@JsonIdentityInfo`; otherwise Jackson
does not know to look for, or keep track of, anchors (ids for values
to reference) or references.

But one limitation is that only POJO types support Object Id handling,
and here references would be to Lists of Strings (or maybe Lists of
Lists). In theory it would be possible to handle Object Ids for
Collection, Map and array types, but they are not supported at this
point.

It might, however, be possible for you to create POJO type that gets
serialized as yaml/json Array, just like List (and deserialized from
as well). This could work by using combination of `@JsonValue` (to get
`List` to serialize) and `@JsonCreator` annotated constructor that
takes actual `List` value you want; or, using Converters. Either way
once you get that working, and type itself annotated with
`@JsonIdentityInfo` it should work.

I know this is sub-optimal and leaves out some valid YAML cases. But
it just might work for your usage.

I hope this helps,

-+ Tatu +-

-- 
You received this message because you are subscribed to the Google Groups 
"jackson-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to