On Tuesday, February 12, 2019 at 11:43:38 PM UTC-5, John Passaro wrote:
>
> On Tue, Feb 12, 2019, 23:02 Tatu Saloranta wrote:
>
>> On Tue, Feb 12, 2019 at 1:18 PM John Passaro 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.
>> >
>> > [...]
>> >
>> >
>> > 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.
>> >
>> > [...]
>> >
>> > 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"])
>> >
>> > [...]
>> >
>> > 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.
>
> Sadly this did not work. Here is my best shot based on how I understood 
the suggestion:

@JsonIdentityInfo(generator = ObjectIdGenerators.None.class)
class ScratchModel {
    @JsonProperty("contents")
    @JsonIdentityInfo(generator = ObjectIdGenerators.None.class)
    Map<String, Config> contents;

    @JsonProperty("misc")
    @JsonIdentityInfo(generator = ObjectIdGenerators.None.class)
    Misc misc;

    @JsonIdentityInfo(generator = ObjectIdGenerators.None.class)
    static class Config {
        @JsonProperty("header")
        String header;

        @JsonProperty("labels")
        @JsonIdentityInfo(generator = ObjectIdGenerators.None.class)
        List<String> labels;

    }

    @JsonIdentityInfo(generator = ObjectIdGenerators.None.class)
    private static class Misc {
        @JsonCreator
        Misc(List<MiscInner> inners) { }
    }


    @JsonIdentityInfo(generator = ObjectIdGenerators.None.class)
    private static class MiscInner {
        @JsonCreator
        MiscInner(List<String> strings) { }
    }
}

So I broke down the "misc" field, previously List<List<String>>, into a 
type Misc that creates itself from List<MiscInner>, and MiscInner which 
creates itself from List<String>. I added the @JsonIdentityInfo annotation 
to every class and property that could plausibly need it.

Still getting the same error!

Here is the failing YAML again, for reference:

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

-- 
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