On Fri, Sep 10, 2021 at 9:02 PM Mark Gibson <[email protected]> wrote:
>
> Hi,
>
> I have a case where a map is used to store many sets of values.
>
> Map<String, Set<?>>
>
> Each set instance is a set of homogenous data types. But the different
> entries in the map hold a heterogenous collection of set types. Difficult to
> put in to English, but the example code below is actually quite simple. The
> description here is to imply that the set always has to be Set<?> and can't
> be fully typed.
>
> Obviously, to successfully deserialize such a heterogeneous map, type
> information must be included in the serialized Json. This is achievable by
> configuring the ObjectMapper. For example,
>
> mapper.enableDefaultTyping( );
>
> means all type information is recorded in the serialized JSON. However, I'm
> trying to use @JonTypeInfo attribute so that callers of our library do not
> need to remember to use a correctly configured ObjectMapper. JsonTypeInfo
> seems to work for a simple set, but does not work when applied to the map ...
>
> public class MyTest
> {
> @JsonTypeInfo(
> use = JsonTypeInfo.Id.CLASS,
> include = JsonTypeInfo.As.PROPERTY,
> property = "@type",
> visible = true
> )
> public enum MyEnum
> {
> ONE,
> TWO,
> THREE
> }
>
> @JsonAutoDetect( fieldVisibility = JsonAutoDetect.Visibility.NONE,
> getterVisibility = JsonAutoDetect.Visibility.NONE, setterVisibility =
> JsonAutoDetect.Visibility.NONE, isGetterVisibility =
> JsonAutoDetect.Visibility.NONE )
> public static class MyClass
> {
> @JsonProperty( )
> MyEnum singleEnum;
>
> @JsonTypeInfo(
> use = JsonTypeInfo.Id.CLASS,
> include = JsonTypeInfo.As.PROPERTY,
> property = "@type",
> visible = true
> )
> @JsonProperty( )
> Set<?> enumSet;
>
> @JsonProperty( )
> @JsonTypeInfo(
> use = JsonTypeInfo.Id.CLASS,
> include = JsonTypeInfo.As.PROPERTY,
> property = "@type",
> visible = true
> )
> Map<String, Set<?>> mapOfEnumSets = new LinkedHashMap<>( );
> }
>
> public static void main( String[] args ) throws JsonProcessingException
> {
> MyClass mc = new MyClass( );
> mc.singleEnum = MyEnum.TWO;
> mc.enumSet = Stream.of( MyEnum.ONE, MyEnum.TWO, MyEnum.THREE
> ).collect( Collectors.toSet( ) );
> mc.mapOfEnumSets.put( "firstKey", Stream.of( MyEnum.ONE, MyEnum.TWO,
> MyEnum.THREE ).collect( Collectors.toSet( ) ) );
>
> ObjectMapper om = new ObjectMapper( );
>
> String jsonString = om.writeValueAsString( mc );
>
> System.out.println( jsonString );
> }
> }
>
>
> This is the serialized JSON:
>
> {"singleEnum":["MyTest$MyEnum","TWO"],"enumSet":[["MyTest$MyEnum","TWO"],["MyTest$MyEnum","THREE"],["MyTest$MyEnum","ONE"]],"mapOfEnumSets":{"firstKey":["java.util.HashSet",["TWO","THREE","ONE"]]}}
> .
> Is it possible to get the type info generated for the contents of the sets in
> the map using JsonTypeInfo and/or other annotations? Or are we limited to
> the direct configuration of the ObjectMapper?
Not sure I understand the exact question, but couple of notes that may help:
1. Use of `@JsonTypeInfo` on Enum types does not really make sense
(here for MyEnum), since enum types can not be extended. (not a big
problem here, but worth mentioning). Adding @JsonTypeInfo on enum has
no effect on Set, Map, since the declared value base type is not
MyEnum.
2. Use of `@JsonTypeInfo` for structured types (Collections, Maps,
arrays) affects main-level values/elements. So, works fine for
`Set<Object>` (which is what `Set<?>` is from Jackson's perspective),
but not really for multiple levels (Map<String, Set<?>> ) -- in latter
case it'd mean "polymorphic subtype of Set<?>"
I assume (2) is the problem wrt nested Maps: polymorphic handling can
only be enabled for the immediate child value, but not to the
innermost level.
You could, however, declare your own special `Set` type there... something like
@JsonTypeInfo(....)
static class MySet<T> extends HashSet<T> { }
and then use that
> Map<String, MySet<?> mapOfEnumSets = new LinkedHashMap<>( );
in declaration. This would, I think, force inclusion and use of
polymorphic type information.
-+ 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 view this discussion on the web visit
https://groups.google.com/d/msgid/jackson-user/CAL4a10jGUvqaYVWRnht5TiOEMLM2%2B%3Dc7zYGvS7XuaAFw-SKhqA%40mail.gmail.com.