JsonIgnoreProperties not working - jackson

I have the following simple class:
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
#JsonIgnoreProperties({ "thirdField" })
public class Message {
private TypeA type;
private String producer;
//Getters and Setters
}
in my test class
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Test {
public void testMethd() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(MapperFeature.USE_ANNOTATIONS, true);
Class<T> instanceType = Message.class;
String msgBody = "{\"producer\": \"clientApp\", \"type\": \"aType\", \"thirdField\": []}";
objectMapper.readValue(msgBody, instanceType);
}
}
All I am trying to do is to convert the above json string into Message class and ignore the 'thirdField'. But I keep getting
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "thirdField" (class Message), not marked as ignorable (2 known properties: , "type", "producer"])

You've mixed different versions of Jackson.
Notice that you import JsonIgnoreProperties from org.codehaus.jackson.annotate (version 1.x)
while you're using ObjectMapper from com.fasterxml.jackson.databind (version 2.x).

Try using the last Jackson version (2.4):
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
#JsonIgnoreProperties({"id"})
Here you can find an example where it's implement using version 2.4:
http://www.ibm.com/developerworks/java/library/j-hangman-app/index.html

I found a Solution to this.
Try to add
#JsonSerialize(include= JsonSerialize.Inclusion.NON_EMPTY)
About your class
#JsonSerialize(include= JsonSerialize.Inclusion.NON_EMPTY)
class ResponseModel {
//your properties here
#JsonIgnoreProperties("messageList","contactList","sender")
var contactList= ArrayList<ContactModel>()
}
That will solve your issue buddy.

It didn't work for me any of the above answers, i found a workaround that I have reinitialized the object and values (copied the object).

Related

Why jackson is not serializing this?

#Data
public class IdentificacaoBiometricaDto {
private Integer cdIdentifBiom;
private String nrMatricula;
private String deImpressaoDigital;
private Integer cdFilialAtualizacao;
}
I am using retrofit 2.6.1, jackson 2.9.9 and lombok 1.8.10.
The exception is:
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class br.com.clamed.modelo.loja.dto.central.IdentificacaoBiometricaDto and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77)
at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1191)
at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:313)
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:71)
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:33)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:400)
at com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1392)
at com.fasterxml.jackson.databind.ObjectWriter._configAndWriteValue(ObjectWriter.java:1120)
at com.fasterxml.jackson.databind.ObjectWriter.writeValueAsBytes(ObjectWriter.java:1017)
at retrofit2.converter.jackson.JacksonRequestBodyConverter.convert(JacksonRequestBodyConverter.java:34)
at retrofit2.converter.jackson.JacksonRequestBodyConverter.convert(JacksonRequestBodyConverter.java:24)
at retrofit2.ParameterHandler$Body.apply(ParameterHandler.java:355)
... 14 more
The object mapper:
return new ObjectMapper().registerModule(new ParameterNamesModule())
.registerModule(new Jdk8Module())
.registerModule(new JavaTimeModule())
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
I am setting all fields, when passing it to a request body, retrofit fails because jackson could not serialize the object.
Retrofit call:
#POST("/usuario/v1.0/cadastraBiometria")
Call<IdentificacaoBiometricaDto> cadastraBiometria(#Body IdentificacaoBiometricaDto identificacaoBiometricaDto);
Rest service:
#RestController
#RequestMapping("/usuario")
public class UsuarioController {
#PostMapping(value = "/v1.0/cadastraBiometria")
public ResponseEntity<IdentificacaoBiometricaDto> cadastraBiometria(#RequestBody IdentificacaoBiometricaDto identificacaoBiometricaDto) {
}
}
Update:
If I change the retrofit converter to Gson it works;
If I serialize it using Jackson directly, it works;
Removing lombok makes no difference;
Found the problem. The biometric reader library was causing this. For some reason it's incompatible with openjdk-11 and is causing all sort of unrelated problems.
Yes, very weird. But the lib is very poorly done.

Deserializing guava optional<long> is failing

I am serializing a guava optional using jackson(version:2.9.4).
When i am deserializing, i am getting below exception:
Cannot deserialize instance of 'java.lang.Long' out START_OBJECT token.
When i debug the value during deserialization, i noticed that the value is coming as "Optional(present=true)" rather than the value present inside Optional.
I looked at the object mapper, and "GuavaModule()" is already being registered with the object mapper.
Please let me know if i am missing anything.
With registering the GuavaModule of
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-guava</artifactId>
</dependency>
…and the following bean…
import com.google.common.base.Optional;
import lombok.Data;
import lombok.NoArgsConstructor;
#Data
#NoArgsConstructor
public class GuavaBean {
private Optional<Long> abc;
}
…this gives me a green test…
import static org.assertj.core.api.Assertions.assertThat;
import com.fasterxml.jackson.datatype.guava.GuavaModule;
[…]
#Test
public void guava() throws JsonParseException, JsonMappingException, IOException {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new GuavaModule());
GuavaBean bean = new GuavaBean(Optional.of(9l));
String beanSerialized = objectMapper.writeValueAsString(bean);
assertThat(beanSerialized).isEqualTo("{\"abc\":9}");
GuavaBean optLong = objectMapper.readValue(beanSerialized, GuavaBean.class);
assertThat(optLong.getAbc().get()).isEqualTo(9);
}
However, if I accidentally use java.util.Optional instead of com.google.common.base.Optional, then the beahviour is exactly like you wrote.

Lombok + Intellij: cannot resolve method of super class

I have a superclass
#Data
#AllArgsConstructor
#NoArgsConstructor
#Builder
public class ErrorResponse {
#JsonProperty
private String message;
}
And I have a child one
#Data
#NoArgsConstructor
#AllArgsConstructor
#Builder(builderMethodName = "_builder") // add custom builder name to avoid compilation issue 'return type is not compatible...'
#EqualsAndHashCode(callSuper=true)
public class AskQuestionErrorResponse extends ErrorResponse {
#JsonProperty
private String status;
#Builder(builderMethodName = "_builder") // add custom builder name to avoid compilation issue 'return type is not compatible...'
private AskQuestionErrorResponse(String status, String message){
super(message);
this.status = status;
}
}
When I use a builder to create an object like this
AskQuestionErrorResponse._builder()
.status(1)
.message("my message here").build()
Intellij shows me message in red and there is an issue cannot resolve method 'message(java.lang.String)' Anyway project compiles and runs even with this error.
I've already enabled annotations precessing.
If I comment field from superclass like this
AskQuestionErrorResponse._builder()
.status(ex.getStatus().getValue()
//.message(ex.getMessage()
).build()
It works. It seems that it does not see superclass members. I've also tried maven clean and install, rebuild project.
UPDATE
Lombok plugin is installed
Annotation Processors are enabled in Preferences and in Default preferences
I found it. If you take a look to my class you'll see two #Builder annotations. I removed first one and magic happens. Now my class looks like this and there is no warning
#Data
#NoArgsConstructor
#AllArgsConstructor
#EqualsAndHashCode(callSuper=true)
public class AskQuestionErrorResponse extends ErrorResponse {
#JsonProperty
private String status;
#Builder(builderMethodName = "_builder") // add custom builder name to avoid compilation issue 'return type is not compatible...'
public AskQuestionErrorResponse(String status, String message){
super(message);
this.status = status;
}
}
Hope it helps :)
You need to install the Intellij Lombok plugin so that it can understand the annotations before the compilation to byte code.
https://projectlombok.org/setup/intellij

redefine static methods with ByteBuddy

Can homebody help me please to give me a hint how to redefine static methods using byte-buddy 1.6.9 ?
I have tried this :
public class Source {
public static String hello(String name) {return null;}
}
public class Target {
public static String hello(String name) {
return "Hello" + name+ "!";
}
}
String helloWorld = new ByteBuddy()
.redefine(Source.class)
.method(named("hello"))
.intercept(MethodDelegation.to(Target.class))
.make()
.load(getClass().getClassLoader())
.getLoaded()
.newInstance()
.hello("World");
I got following Exception :
Exception in thread "main" java.lang.IllegalStateException: Cannot inject already loaded type: class delegation.Source
Thanks
Classes can only be loaded once by each class loader. In order to replace a method, you would need to use a Java agent to hook into the JVM's HotSwap feature.
Byte Buddy provides a class loading strategy that uses such an agent, use:
.load(Source.class.getClassLoader(),
ClassReloadingStrategy.fromInstalledAgent());
This does however require you to install a Java agent. On a JDK, you can do so programmatically, by ByteBuddyAgent.install() (included in the byte-buddy-agent artifact). On a JVM, you have to specify the agent on the command line.

Jackson unrecognized field exception but field is in JSON

I am using Spring Integration to consume a message with a JSON Payload.
In my spring context I have
<integration:channel id="jsonToMyMessageConverterChannel"/>
<integration:json-to-object-transformer
type="com.acme.messaging.message.MyMessage"
input-channel="jsonToMyMessageConverterChannel"
output-channel="myMessageUpdateChannel"/>
My message related objects are:
MyMessage.java
#JsonIgnoreProperties(ignoreUnknown=true)
public class MyMessage {
#JsonProperty
private String timestamp;
#JsonProperty("msgs")
private List<Message> messages;
// Getters and Setters...
}
Message.java
#JsonIgnoreProperties(ignoreUnknown=true)
public class Message {
#JsonProperty
private Integer msgId;
#JsonProperty("msgText")
private String text;
// Getters and Setters...
}
When the json transformer attempts to convert the message to an object it fails with
Caused by: org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Unrecognized field "msgs" (Class com.acme.messaging.message.MyMessage), not marked as ignorable
The JSON payload definitely has msgs which is an array that has objects which represent the Message.java class.
Can any one suggest reasons why the exception occurs given that the JSON has the field that is being complained about and the class itself is also annotated to ignore unknown fields?
Update
After some debugging it looks like the #JsonProperty("msgs") annotations aren't being use, for some reason.
This works fine for me...
#Test
public void test() throws Exception {
MyMessages mm = new MyMessages();
MyMessage m = new MyMessage();
m.setMsgId(1);
m.setText("foo");
mm.setMessages(Arrays.asList(m));
mm.setTimestamp("123");
#SuppressWarnings("deprecation")
ObjectToJsonTransformer otjt = new ObjectToJsonTransformer(new ObjectMapper());
Message<?> message = new GenericMessage<MyMessages>(mm);
message = otjt.transform(message);
System.out.println(message);
#SuppressWarnings("deprecation")
JsonToObjectTransformer<MyMessages> jtot = new JsonToObjectTransformer<MyMessages>(MyMessages.class, new ObjectMapper());
message = jtot.transform(message);
mm = (MyMessages) message.getPayload();
System.out.println(mm.getTimestamp());
System.out.println(mm.getMessages().get(0).getText());
}
(I changed your classnames slightly to avoid colliding with Message<?>)
Resulting in...
[Payload={"timestamp":"123","msgs":[{"msgId":1,"msgText":"foo"}]}][Headers={timestamp=1373997151738, id=f2425f36-a500-4aee-93a4-e7e0240ce0f1, content-type=application/json}]
123
foo
Do you have both jackson 1.x (codehaus) and 2.x (fasterxml) on the classpath, and using Spring Integration 3.0.0?
If they're both on the classpath, SI will use Jackson 2.x, by default, (which won't understand 1.x annotations).
Or, I guess - are you using Jackson2 (fasterxml) annotations? Spring Integration 2.x uses Jackson 1 (codehaus).
EDIT:
In order to support both versions of Jackson, you can annotate the class with both annotations...
#JsonProperty("msgs")
#com.fasterxml.jackson.annotation.JsonProperty("msgs")
public List<MyMessage> messages;