Thank you. I've been digging around jackson code while trying to resolve the issue and would be interested in contributing on this if you're open to it.
I'm still stuck with purportedly valid YAML that I cannot parse. Maybe you've seen my follow-up reply where I tried to implement the workaround you mentioned? If you can offer any further suggestions for how I can make this work, with a mountain of annotations if necessary, I would be very grateful. John Passaro (917) 678-8293 On Thu, Feb 14, 2019 at 1:42 PM Tatu Saloranta <[email protected]> wrote: > On Tue, Feb 12, 2019 at 8:43 PM John Passaro <[email protected]> > wrote: > > > > On Tue, Feb 12, 2019, 23:02 Tatu Saloranta <[email protected] wrote: > >> > >> 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 +- > > > > > > I will certainly try this out, it does seem like it would address my > need. Thank you for the close attention to the example and for your > suggestion. If it works I'll post my findings (i.e. working example) here > and maybe add to those SO questions. > > > > It seems to me there might be a friendlier experience if there was a > YamlParser.Feature to treat the entire document as having the > JsonIdentityInfo annotation, including Lists and Maps and their contents - > that is, resolving anchor references everywhere without the need for > indicating where the user expects them to be. I don't know enough to assert > that this is closer to the intention of the anchor/reference feature or of > an average document that uses it, but it is closer to how PyYAML treats > them, which I've found very useful. I hope you'll consider supporting such > usage. > > > > Regardless, thank you for your help and for your work on this powerful > library. > > Yes, it is true that for YAML documents the idea of using "default > identity" (similar to "default typing" for polymorphic type handling) > would be useful. > Unfortunately I am not sure how practical it would be for general > case, one problem being the limited support for non-POJO types. > > In practice one could achieve something like this by custom > `AnnotationIntrospector` that basically "finds" equivalent of > `@JsonIdentityInfo` on every introspected type. > > But as to more general handling... I wonder if `JsonNode` could be > forced (with a feature or YAMLMapper setting) to support anchors/refs > and in THAT case you could first resolve all of these and THEN map to > actual POJOs. > > I will file an issue for that -- I can't promise I can make that > happen, but I think that is a reasonable idea and could help tackle > this completely without requiring annotations. > > -+ Tatu +- > > -- > You received this message because you are subscribed to a topic in the > Google Groups "jackson-user" group. > To unsubscribe from this topic, visit > https://groups.google.com/d/topic/jackson-user/b3ucK2emRbE/unsubscribe. > To unsubscribe from this group and all its topics, 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. > -- 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.
