On Wed, Jan 2, 2019 at 4:09 PM matt Smith <[email protected]> wrote:
> I just added @JsonAnyGetter to the wrapper class and now when I write > mapper.writeValueAsString(wrapper), it gives the expected output. I don't > understand why but it just works! > > @JsonAnyGetter > @JsonSerialize(contentUsing = ItemRowSerializer.class) > private Map<RecordDomain, ItemRow> foo; > > > > > Good thinking -- such usage does indeed get rid of extra wrapper, as entries from Map are included directly in enclosing JSON Object. That is actually a neat example of sort of "off-label" usage: something that is supported (it's not accidental), but different from more common approach of simply using serializer for known type like `String`. -+ Tatu +- > On Monday, December 24, 2018 at 4:56:27 PM UTC-8, Tatu Saloranta wrote: >> >> On Fri, Dec 21, 2018 at 2:30 PM matt Smith <[email protected]> >> wrote: >> > >> > In the above case, I called >> `mapper.writeValueAsString(wrapper.getFoo());` >> > >> > I changed to the following (moved to annotation to the field level). >> when I write using `mapper.writeValueAsString(wrapper)`, I see the >> expected serialization applied. However, extra node "foo" is added at root. >> is there a way to not have it? >> >> No, if applied as content serializer, Map serializer will produce >> wrapping. >> You would need custom serializer that just serializes entries and not >> enclose them within START_OBJECT / END_OBJECT. >> >> -+ Tatu +- >> >> > public class Wrapper { >> > >> > >> > @JsonSerialize(contentUsing = ItemRowSerializer.class) >> > private Map<RecordDomain, ItemRow> foo; >> > >> > >> > public Wrapper(Map<RecordDomain, ItemRow> fooz) { >> > foo = new HashMap<>(fooz); >> > } >> > >> > >> > public Map<RecordDomain, ItemRow> getFoo() { >> > return foo; >> > } >> > >> > >> > public void setFoo(Map<RecordDomain, ItemRow> foo) { >> > this.foo = foo; >> > } >> > } >> > >> > >> > On Friday, December 21, 2018 at 1:52:41 PM UTC-8, matt Smith wrote: >> >> >> >> even moving annotation to the field did not work. >> >> Note I have annotated class ItemRow class which ofcourse i can't since >> it is part of legacy code. >> >> >> >> On Friday, December 21, 2018 at 12:49:21 PM UTC-8, Tatu Saloranta >> wrote: >> >>> >> >>> On Fri, Dec 21, 2018 at 12:06 AM matt Smith <[email protected]> >> wrote: >> >>> > >> >>> > so I have made this wrapper and annotated getter with >> @JsonSerialize. however, I do not see it being applied. what is wrong here? >> >>> >> >>> That looks like it should work. If not, a unit test & issue would >> make sense. >> >>> >> >>> -+ Tatu +- >> >>> >> >>> > >> >>> > public class Wrapper { >> >>> > >> >>> > >> >>> > private Map<RecordDomain, ItemRow> foo; >> >>> > >> >>> > >> >>> > public Wrapper(Map<RecordDomain, ItemRow> fooz) { >> >>> > foo = new HashMap<>(fooz); >> >>> > } >> >>> > >> >>> > >> >>> > @JsonSerialize( contentUsing = ItemRowSerializer.class) >> >>> > public Map<RecordDomain, ItemRow> getFoo() { >> >>> > return foo; >> >>> > } >> >>> > >> >>> > >> >>> > public void setFoo(Map<RecordDomain, ItemRow> foo) { >> >>> > this.foo = foo; >> >>> > } >> >>> > } >> >>> > >> >>> > >> >>> > On Thursday, December 20, 2018 at 1:25:59 PM UTC-8, Tatu Saloranta >> wrote: >> >>> >> >> >>> >> On Thu, Dec 20, 2018 at 11:22 AM matt Smith <[email protected]> >> wrote: >> >>> >> > >> >>> >> > I encountered a case where class level JsonSerializable >> annotation does not require registration with Simple Module but method >> level does. >> >>> >> >> >>> >> Hmmh. This seems odd, let's see. >> >>> >> >> >>> >> > Here is the example I tried >> >>> >> > >> >>> >> > @JsonSerialize(using = ItemRowSerializer.class ) >> >>> >> > private ItemRow tes >> >>> >> > tItem(){ >> >>> >> > return new ItemRow("abc", Arrays.asList("item1", >> "item2", "item3")); >> >>> >> > } >> >>> >> > >> >>> >> > >> >>> >> > I test it out like this >> >>> >> > >> >>> >> > >> >>> >> > String jsonResult = new >> ObjectMapper().writeValueAsString(testItem()); >> >>> >> > System.out.println(jsonResult); >> >>> >> > >> >>> >> > I noticed that jsonString did not serialize using >> ItemRowSerializer. >> >>> >> >> >>> >> Ah. No, it won't. Jackson does not see you calling the method; >> Jackson >> >>> >> sees the object you pass, which was returned by the method. There >> is >> >>> >> no linkage there: Jackson can only introspects classes you pass to >> it. >> >>> >> >> >>> >> > However, when I did this, it gave the expected jsonString >> >>> >> > >> >>> >> > >> >>> >> > SimpleModule module = new SimpleModule() >> >>> >> > module.addSerializer(ItemRowSerializer.class) >> >>> >> > mapper.register(module); >> >>> >> > String jsonResult = new >> ObjectMapper().writeValueAsString(testItem()); >> >>> >> > System.out.println(jsonResult); >> >>> >> > >> >>> >> > >> >>> >> > On the otherhand, if I had my ItemRow class annoated with >> @JsonSerializable, there was no need with module at all. >> >>> >> >> >>> >> I think you mean `@JsonSerialize` here (there is interface type >> >>> >> `JsonSerializable`, but no annotation). >> >>> >> >> >>> >> > i.e >> >>> >> > >> >>> >> > @JsonSerializable(using = ItemRowSerailizer >> >>> >> > public class ItemRow<T> {...} >> >>> >> > >> >>> >> > >> >>> >> > Since I am passing this serialized object over the wire, I do >> not prefer to write to mapper and send string representation across. >> >>> >> > >> >>> >> > how would I go about getting method level annotation working >> without module registration? >> >>> >> >> >>> >> Method level annotations only work when property is accessed via >> >>> >> method (or field) in question. >> >>> >> >> >>> >> So if you had something like: >> >>> >> >> >>> >> public class Rows >> >>> >> @JsonSerialize(using = .... ) >> >>> >> public ItemRow<Type> getRows() { ... } >> >>> >> } >> >>> >> >> >>> >> and serialized an instance of `Rows`, serializer would be found. >> But >> >>> >> for root values, there is no such reference. >> >>> >> >> >>> >> On related note, I strongly recommend always using a wrapper type >> >>> >> around generic values, so that root value is never of generic >> type. >> >>> >> Reason for this is that Java Type Erasure will often cause >> problems if >> >>> >> attempting to pass an instance of generic type -- so Jackson can >> not >> >>> >> detect intended type (all it sees is type variable from class >> >>> >> declaration). >> >>> >> >> >>> >> So, attempts to serialize, say, Row<T>, will be seen as `Row<?>`, >> and >> >>> >> possibly (although not always) cause issues in finding handlers >> for >> >>> >> the type -- for example, if value type has annotations, they may >> not >> >>> >> be visible. >> >>> >> >> >>> >> -+ 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. >> > >> > -- >> > 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. >> > -- > 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. > -- 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.
