Re: [jackson-user] Field level Custom Annotation for JsonPointer expression

2023-09-19 Thread Tatu Saloranta
On Tue, Sep 19, 2023 at 7:19 AM Aditya Pant  wrote:
>
> I have removed all lombok annotations from Person and Address classes. Then 
> added getters and setters.
>
> As earlier it reached to JsonPointerPropertyIntrospector and created 
> instance, however it didn't invoke 
> JsonPointerPropertyDeserializer.deserialize(). Similar behavior with 
> ContextualDeserilizer.

It seems very odd that an instance was created but not used.

Could you file an issue for jackson-databind Github project, including
a minimal reproduction of method not getting called -- it's ok if code
wouldn't do quite what it supposed to as long as it's clear method is
not called.

>
> Another challenge, in the input json "requestModel" contains mixed data 
> (address, product, person). During deserialization they need to be set on 
> individual member (objects) on a person object. @JsonProperty("requestModel") 
> only works for one field. Adding it to address and product not allowed it 
> seems. "Conflicting getter definitions for property 'requestModel' "

I'd need to see full class definition for this to make sure I
understand the issue.

You can add that to the issue filed.

-+ Tatu +-

>
> I hope there is a way to combine JsonPath and Jackson behavior
>
> On Tuesday, September 19, 2023 at 11:12:55 PM UTC+10 Aditya Pant wrote:
>>
>> Thank you Tatu for your insights. Appreciate it.
>> You are right it could be annotations are not copied during annotation 
>> processing.
>> Definitely I will give it a try without lombok annotations.
>>
>>
>>
>> On Tuesday, September 19, 2023 at 2:27:49 PM UTC+10 Tatu Saloranta wrote:
>>>
>>> On Sun, Sep 17, 2023 at 9:39 PM Aditya Pant  wrote:
>>> >
>>> > Hello Jackson community,
>>> >
>>> > The input Json have nested fields and different field names. I am looking 
>>> > for a way to deserilize using JsonPointer espression (because it allows 
>>> > path lookup).
>>> >
>>> > I have tried several approaches but none of them worked so far.
>>> >
>>> > - Tried using AnnotationIntrospector = introspector gets invoked which 
>>> > returns a custom deserializer from overridden findDeserializer(). 
>>> > However, custom JsonDeserialiser.deserialize() never invoked on 
>>> > mapper.readValue()
>>> >
>>> > - Tried using ContextualDeserilizer = it gets invoked which returns a 
>>> > custom deserializer. However, custom JsonDeserialiser.deserialize() never 
>>> > invoked on mapper.readValue()
>>>
>>> Those both should work. I didn't see anything obviously wrong in your
>>> code, but there are 2 things that might be problematic: I'll add notes
>>> below.
>>>
>>> >
>>> > The customer deserialiser only invoked when it is declared on the class 
>>> > (not on field).
>>> >> Following are classes:
>>> > Using jackson with lombok
>>>
>>> This might be problematic -- possibly annotations might not be copied
>>> into generated classes?
>>> Either way, trying things out with regular POJO could rule out Lombok
>>> as being problematic
>>> (Jackson should work just fine with Lombok but there have been some
>>> issues in the past)
>>>
>>> >
>>> > // custom annotation
>>> >
>>> > @Target({ElementType.FIELD})
>>> > @Retention(RetentionPolicy.RUNTIME)
>>> > @Documented
>>> > public @interface JsonPointerProperty {
>>> >
>>> > String value();
>>> > }
>>> >
>>> > // Person POJO
>>> >
>>> > @Data
>>>
>>>
>>> > @NoArgsConstructor
>>> > @AllArgsConstructor
>>> > @JsonIgnoreProperties(ignoreUnknown = true)
>>>
>>> ^^^ I always recommend removing this annotation when troubleshooting,
>>> it can easily mask problems.
>>>
>>> > public class Person {
>>> > private String name;
>>> > private Address address;
>>> > }
>>> >
>>> > // Address POJO
>>> >
>>> > @Data
>>> > @NoArgsConstructor
>>> > @AllArgsConstructor
>>> > @JsonIgnoreProperties(ignoreUnknown = true)
>>> > public class Address {
>>> >
>>> > // using custom annotation
>>> > @JsonPointerProperty("/requestModel/streetName")
>>> > private String street;
>>> > private String city;
>>> > private String postcode;
>>> > }
>>> >
>>> > // introspector
>>> >
>>> > public class JsonPointerPropertyIntrospector
>>> > extends NopAnnotationIntrospector {
>>> >
>>> > @Override
>>> > public Object findDeserializer(Annotated am) {
>>> >
>>> > final JsonPointerProperty jsonPointerProperty = 
>>> > am.getAnnotation(JsonPointerProperty.class);
>>> > if (jsonPointerProperty != null) {
>>> > return new JsonPointerPropertyDeserializer(
>>> > jsonPointerProperty.value(),
>>> > am.getType().getRawClass()
>>> > );
>>> > }
>>> >
>>> > return super.findDeserializer(am);
>>> > }
>>> > }
>>> >
>>> > // custom deserializer
>>> > public class JsonPointerPropertyDeserializer
>>> > extends JsonDeserializer {
>>> >
>>> > private final String jsonPath;
>>> > private final Class clazz;
>>> >
>>> > public JsonPointerPropertyDeserializer() {
>>> > this(null, null);
>>> > }
>>> >
>>> > public JsonPointerPropertyDeserializer(String jsonPath,
>>> > Class clazz) {
>>> > this.jsonPath = jsonPath;
>>> > this.clazz = clazz;
>>> 

Re: [jackson-user] Field level Custom Annotation for JsonPointer expression

2023-09-19 Thread Aditya Pant

I have removed all lombok annotations from Person and Address classes. Then 
added getters and setters.

As earlier it reached to JsonPointerPropertyIntrospector and created 
instance, however it didn't invoke 
JsonPointerPropertyDeserializer.deserialize(). Similar behavior with 
ContextualDeserilizer.

Another challenge, in the input json "requestModel" contains mixed data 
(address, product, person). During deserialization they need to be set on 
individual member (objects) on a person object. 
@JsonProperty("requestModel") only works for one field. Adding it to 
address and product not allowed it seems. "Conflicting getter definitions 
for property 'requestModel' "

I hope there is a way to combine JsonPath and Jackson behavior

On Tuesday, September 19, 2023 at 11:12:55 PM UTC+10 Aditya Pant wrote:

> Thank you Tatu for your insights. Appreciate it.
> You are right it could be annotations are not copied during annotation 
> processing.
> Definitely I will give it a try without lombok annotations.
>
>
>
> On Tuesday, September 19, 2023 at 2:27:49 PM UTC+10 Tatu Saloranta wrote:
>
>> On Sun, Sep 17, 2023 at 9:39 PM Aditya Pant  wrote: 
>> > 
>> > Hello Jackson community, 
>> > 
>> > The input Json have nested fields and different field names. I am 
>> looking for a way to deserilize using JsonPointer espression (because it 
>> allows path lookup). 
>> > 
>> > I have tried several approaches but none of them worked so far. 
>> > 
>> > - Tried using AnnotationIntrospector = introspector gets invoked which 
>> returns a custom deserializer from overridden findDeserializer(). However, 
>> custom JsonDeserialiser.deserialize() never invoked on mapper.readValue() 
>> > 
>> > - Tried using ContextualDeserilizer = it gets invoked which returns a 
>> custom deserializer. However, custom JsonDeserialiser.deserialize() never 
>> invoked on mapper.readValue() 
>>
>> Those both should work. I didn't see anything obviously wrong in your 
>> code, but there are 2 things that might be problematic: I'll add notes 
>> below. 
>>
>> > 
>> > The customer deserialiser only invoked when it is declared on the class 
>> (not on field). 
>> >> Following are classes: 
>> > Using jackson with lombok 
>>
>> This might be problematic -- possibly annotations might not be copied 
>> into generated classes? 
>> Either way, trying things out with regular POJO could rule out Lombok 
>> as being problematic 
>> (Jackson should work just fine with Lombok but there have been some 
>> issues in the past) 
>>
>> > 
>> > // custom annotation 
>> > 
>> > @Target({ElementType.FIELD}) 
>> > @Retention(RetentionPolicy.RUNTIME) 
>> > @Documented 
>> > public @interface JsonPointerProperty { 
>> > 
>> > String value(); 
>> > } 
>> > 
>> > // Person POJO 
>> > 
>> > @Data 
>>
>>
>> > @NoArgsConstructor 
>> > @AllArgsConstructor 
>> > @JsonIgnoreProperties(ignoreUnknown = true) 
>>
>> ^^^ I always recommend removing this annotation when troubleshooting, 
>> it can easily mask problems. 
>>
>> > public class Person { 
>> > private String name; 
>> > private Address address; 
>> > } 
>> > 
>> > // Address POJO 
>> > 
>> > @Data 
>> > @NoArgsConstructor 
>> > @AllArgsConstructor 
>> > @JsonIgnoreProperties(ignoreUnknown = true) 
>> > public class Address { 
>> > 
>> > // using custom annotation 
>> > @JsonPointerProperty("/requestModel/streetName") 
>> > private String street; 
>> > private String city; 
>> > private String postcode; 
>> > } 
>> > 
>> > // introspector 
>> > 
>> > public class JsonPointerPropertyIntrospector 
>> > extends NopAnnotationIntrospector { 
>> > 
>> > @Override 
>> > public Object findDeserializer(Annotated am) { 
>> > 
>> > final JsonPointerProperty jsonPointerProperty = 
>> am.getAnnotation(JsonPointerProperty.class); 
>> > if (jsonPointerProperty != null) { 
>> > return new JsonPointerPropertyDeserializer( 
>> > jsonPointerProperty.value(), 
>> > am.getType().getRawClass() 
>> > ); 
>> > } 
>> > 
>> > return super.findDeserializer(am); 
>> > } 
>> > } 
>> > 
>> > // custom deserializer 
>> > public class JsonPointerPropertyDeserializer 
>> > extends JsonDeserializer { 
>> > 
>> > private final String jsonPath; 
>> > private final Class clazz; 
>> > 
>> > public JsonPointerPropertyDeserializer() { 
>> > this(null, null); 
>> > } 
>> > 
>> > public JsonPointerPropertyDeserializer(String jsonPath, 
>> > Class clazz) { 
>> > this.jsonPath = jsonPath; 
>> > this.clazz = clazz; 
>> > } 
>> > 
>> > @Override 
>> > public Object deserialize(JsonParser parser, DeserializationContext 
>> ctx) 
>> > throws IOException, JacksonException { 
>> > 
>> > // not reaching here 
>> > JsonNode jsonNode = parser.readValueAs(JsonNode.class); 
>> > JsonNode at = jsonNode.at(jsonPath); 
>> > 
>> > String value = ctx.readTreeAsValue(jsonNode, String.class); 
>> > 
>> > System.out.println(value); 
>> > 
>> > return null; 
>> > } 
>> > } 
>> > 
>> > 
>> > // Unit test 
>> > 
>> > class PersonTest { 
>> > String json; 
>> > 
>> > @BeforeEach 
>> > 

Re: [jackson-user] Field level Custom Annotation for JsonPointer expression

2023-09-19 Thread Aditya Pant
Thank you Tatu for your insights. Appreciate it.
You are right it could be annotations are not copied during annotation 
processing.
Definitely I will give it a try without lombok annotations.



On Tuesday, September 19, 2023 at 2:27:49 PM UTC+10 Tatu Saloranta wrote:

> On Sun, Sep 17, 2023 at 9:39 PM Aditya Pant  wrote:
> >
> > Hello Jackson community,
> >
> > The input Json have nested fields and different field names. I am 
> looking for a way to deserilize using JsonPointer espression (because it 
> allows path lookup).
> >
> > I have tried several approaches but none of them worked so far.
> >
> > - Tried using AnnotationIntrospector = introspector gets invoked which 
> returns a custom deserializer from overridden findDeserializer(). However, 
> custom JsonDeserialiser.deserialize() never invoked on mapper.readValue()
> >
> > - Tried using ContextualDeserilizer = it gets invoked which returns a 
> custom deserializer. However, custom JsonDeserialiser.deserialize() never 
> invoked on mapper.readValue()
>
> Those both should work. I didn't see anything obviously wrong in your
> code, but there are 2 things that might be problematic: I'll add notes
> below.
>
> >
> > The customer deserialiser only invoked when it is declared on the class 
> (not on field).
> >> Following are classes:
> > Using jackson with lombok
>
> This might be problematic -- possibly annotations might not be copied
> into generated classes?
> Either way, trying things out with regular POJO could rule out Lombok
> as being problematic
> (Jackson should work just fine with Lombok but there have been some
> issues in the past)
>
> >
> > // custom annotation
> >
> > @Target({ElementType.FIELD})
> > @Retention(RetentionPolicy.RUNTIME)
> > @Documented
> > public @interface JsonPointerProperty {
> >
> > String value();
> > }
> >
> > // Person POJO
> >
> > @Data
>
>
> > @NoArgsConstructor
> > @AllArgsConstructor
> > @JsonIgnoreProperties(ignoreUnknown = true)
>
> ^^^ I always recommend removing this annotation when troubleshooting,
> it can easily mask problems.
>
> > public class Person {
> > private String name;
> > private Address address;
> > }
> >
> > // Address POJO
> >
> > @Data
> > @NoArgsConstructor
> > @AllArgsConstructor
> > @JsonIgnoreProperties(ignoreUnknown = true)
> > public class Address {
> >
> > // using custom annotation
> > @JsonPointerProperty("/requestModel/streetName")
> > private String street;
> > private String city;
> > private String postcode;
> > }
> >
> > // introspector
> >
> > public class JsonPointerPropertyIntrospector
> > extends NopAnnotationIntrospector {
> >
> > @Override
> > public Object findDeserializer(Annotated am) {
> >
> > final JsonPointerProperty jsonPointerProperty = 
> am.getAnnotation(JsonPointerProperty.class);
> > if (jsonPointerProperty != null) {
> > return new JsonPointerPropertyDeserializer(
> > jsonPointerProperty.value(),
> > am.getType().getRawClass()
> > );
> > }
> >
> > return super.findDeserializer(am);
> > }
> > }
> >
> > // custom deserializer
> > public class JsonPointerPropertyDeserializer
> > extends JsonDeserializer {
> >
> > private final String jsonPath;
> > private final Class clazz;
> >
> > public JsonPointerPropertyDeserializer() {
> > this(null, null);
> > }
> >
> > public JsonPointerPropertyDeserializer(String jsonPath,
> > Class clazz) {
> > this.jsonPath = jsonPath;
> > this.clazz = clazz;
> > }
> >
> > @Override
> > public Object deserialize(JsonParser parser, DeserializationContext ctx)
> > throws IOException, JacksonException {
> >
> > // not reaching here
> > JsonNode jsonNode = parser.readValueAs(JsonNode.class);
> > JsonNode at = jsonNode.at(jsonPath);
> >
> > String value = ctx.readTreeAsValue(jsonNode, String.class);
> >
> > System.out.println(value);
> >
> > return null;
> > }
> > }
> >
> >
> > // Unit test
> >
> > class PersonTest {
> > String json;
> >
> > @BeforeEach
> > void setup() throws IOException {
> > json = "{ 'address': { 'requestModel': { 'streetName': 'some street', 
> 'cityName': 'some city' }}}"
> > .replace(
> > "'",
> > "\""
> > );
> > }
> >
> > @Test
> > void testPerson() throws JsonProcessingException {
> > ObjectMapper mapper = new ObjectMapper();
> > mapper.setAnnotationIntrospector(new JsonPointerPropertyIntrospector());
> >
> > final Person person = mapper.readValue(json, Person.class);
> >
> > assertEquals("some street", person.getAddress().getStreet(), "Street 
> mismatch");
> > }
> > }
> >
> > There is some error parsing `requestModel`, but I was hoping it would at 
> least reach to customer deserializer.
> >
> > Any suggestions or point me what I am doing wrong?
>
> I suspect Lombok might be relevant here; annotations not being copied
> into generated classes.
>
> -+ 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 jackson-user+unsubscr...@googlegroups.com.
To view this discussion 

Re: [jackson-user] Field level Custom Annotation for JsonPointer expression

2023-09-18 Thread Tatu Saloranta
On Sun, Sep 17, 2023 at 9:39 PM Aditya Pant  wrote:
>
> Hello Jackson community,
>
> The input Json have nested fields and different field names. I am looking for 
> a way to deserilize using JsonPointer espression (because it allows path 
> lookup).
>
> I have tried several approaches but none of them worked so far.
>
> - Tried using AnnotationIntrospector = introspector gets invoked which 
> returns a custom deserializer from overridden findDeserializer(). However, 
> custom JsonDeserialiser.deserialize() never invoked on mapper.readValue()
>
> - Tried using ContextualDeserilizer = it gets invoked which returns a custom 
> deserializer. However, custom JsonDeserialiser.deserialize() never invoked on 
> mapper.readValue()

Those both should work. I didn't see anything obviously wrong in your
code, but there are 2 things that might be problematic: I'll add notes
below.

>
> The customer deserialiser only invoked when it is declared on the class (not 
> on field).
>> Following are classes:
> Using jackson with lombok

This might be problematic -- possibly annotations might not be copied
into generated classes?
Either way, trying things out with regular POJO could rule out Lombok
as being problematic
(Jackson should work just fine with Lombok but there have been some
issues in the past)

>
> // custom annotation
>
> @Target({ElementType.FIELD})
> @Retention(RetentionPolicy.RUNTIME)
> @Documented
> public @interface JsonPointerProperty {
>
> String value();
> }
>
> // Person POJO
>
> @Data


> @NoArgsConstructor
> @AllArgsConstructor
> @JsonIgnoreProperties(ignoreUnknown = true)

^^^ I always recommend removing this annotation when troubleshooting,
it can easily mask problems.

> public class Person {
> private String name;
> private Address address;
> }
>
> // Address POJO
>
> @Data
> @NoArgsConstructor
> @AllArgsConstructor
> @JsonIgnoreProperties(ignoreUnknown = true)
> public class Address {
>
> // using custom annotation
> @JsonPointerProperty("/requestModel/streetName")
> private String street;
> private String city;
> private String postcode;
> }
>
> // introspector
>
> public class JsonPointerPropertyIntrospector
> extends NopAnnotationIntrospector {
>
> @Override
> public Object findDeserializer(Annotated am) {
>
> final JsonPointerProperty jsonPointerProperty = 
> am.getAnnotation(JsonPointerProperty.class);
> if (jsonPointerProperty != null) {
> return new JsonPointerPropertyDeserializer(
> jsonPointerProperty.value(),
> am.getType().getRawClass()
> );
> }
>
> return super.findDeserializer(am);
> }
> }
>
> // custom deserializer
> public class JsonPointerPropertyDeserializer
> extends JsonDeserializer {
>
> private final String jsonPath;
> private final Class clazz;
>
> public JsonPointerPropertyDeserializer() {
> this(null, null);
> }
>
> public JsonPointerPropertyDeserializer(String jsonPath,
>Class clazz) {
> this.jsonPath = jsonPath;
> this.clazz = clazz;
> }
>
> @Override
> public Object deserialize(JsonParser parser, DeserializationContext ctx)
> throws IOException, JacksonException {
>
> // not reaching here
> JsonNode jsonNode = parser.readValueAs(JsonNode.class);
> JsonNode at = jsonNode.at(jsonPath);
>
> String value = ctx.readTreeAsValue(jsonNode, String.class);
>
> System.out.println(value);
>
> return null;
> }
> }
>
>
> // Unit test
>
> class PersonTest {
> String json;
>
> @BeforeEach
> void setup() throws IOException {
> json = "{ 'address': { 'requestModel': { 'streetName': 'some street', 
> 'cityName': 'some city' }}}"
> .replace(
> "'",
> "\""
> );
> }
>
> @Test
> void testPerson() throws JsonProcessingException {
> ObjectMapper mapper = new ObjectMapper();
> mapper.setAnnotationIntrospector(new 
> JsonPointerPropertyIntrospector());
>
> final Person person = mapper.readValue(json, Person.class);
>
> assertEquals("some street", person.getAddress().getStreet(), "Street 
> mismatch");
> }
> }
>
> There is some error parsing `requestModel`, but I was hoping it would at 
> least reach to customer deserializer.
>
> Any suggestions or point me what I am doing wrong?

I suspect Lombok might be relevant here; annotations not being copied
into generated classes.

-+ 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 jackson-user+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/jackson-user/CAL4a10isLGpc%3DmeV80J9YvaLHpv9x86wvCFkEZnx0F3TZau1Mw%40mail.gmail.com.