Im getting an InvalidDefinitionException when I try to map a mocked object with ObjectMapper. The object doesn't matter in that case. The code which produces the exception looks like this:
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.writeValueAsString(mock(Object.class));
The resulting exception message is this:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.mockito.internal.creation.bytebuddy.ByteBuddyCrossClassLoaderSerializationSupport and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: org.mockito.codegen.Object$MockitoMock$nY0RyieU["mockitoInterceptor"]->org.mockito.internal.creation.bytebuddy.MockMethodInterceptor["serializationSupport"])
The ObjectMapper comes from jackson-databind v2.14.0, for mockito I'm using version 4.8.1
TL; DR
Mock objects aren't data structures, you can't serialize them by ObjectMapper.
Full answer
You are trying to serialize a mock object which is very special kind of object created by Mockito. It is very different from a ordinary data structures that are processable by ObjectMapper.
What ObjectMapper does is that it looks at the members of a serialized object and tries to serialize each of them. It either knows, how to do that (int, Long...), or it is configured (often right after a new instance creation), or the serialized member has some annotations to tell the ObjectMapper. In your case the mock object has a member of type ByteBuddyCrossClassLoaderSerializationSupport and the ObjectMapper has no idea what to do.
Related
I'm trying to use Jackson in case to serialize and then deserialize an object. The object contains a field -> protected Serializable data
This is where the problem comes from - this data can come from a lot of components. That is why I'm trying to configure the Jackson ObjectMapper instead of adding annotations and changing the code (because for some of the issues I have with the serialization, like this one, I have to change like hundreds of different classes). Is there any way to tell the ObjectMapper to not use .booleanValue() on null fields.
This is how I've currently configured my ObjectMapper:
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(objectMapper.getSerializationConfig().getDefaultVisibilityChecker()
.withFieldVisibility(JsonAutoDetect.Visibility.ANY)
.withGetterVisibility(JsonAutoDetect.Visibility.NONE)
.withSetterVisibility(JsonAutoDetect.Visibility.NONE)
.withCreatorVisibility(JsonAutoDetect.Visibility.NONE));
This usually happens when your object has a property definition of type Boolean but a getter of type boolean. Ensure these types match.
I have search some smilar question in stackoverflow. Referenced question is link .
I try to serialize a prometheus inner class called MetricFamilySamples in simple-client-0.9.0.jar. Package is io.prometheus.client.Collector$MetricFamilySamples. My serilize code is
Enumeration<Collector.MetricFamilySamples> metricFamilySamplesEnumeration = CollectorRegistry.defaultRegistry
.filteredMetricFamilySamples(metricQueryDTO.getParsedQueryStrSet());
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
return objectMapper.writeValueAsString(metricFamilySamplesEnumeration));
I check the class and ensure the field is public. However, I got the following exception:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class java.lang.Object and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: io.prometheus.client.CollectorRegistry$MetricFamilySamplesEnumeration["collectorIter"]->java.util.HashMap$KeyIterator["current"]->java.util.HashMap$Node["com.clougence.cloudcanal.sidecar.component.collect.WorkerStatCollector#6274670b"])
The WorkerStatCollector is a implemented collector extend prometheus Collector. How can I serialize the class with jackson? I use another json serialize tool called fastjson and it can give the result like following picture(part of the result of fastjson serilization).
I would like to deserialize the Spring Boot Environment object returned by:
http://hostname:port/actuator/env
I'm using Jackson's ObjectMapper:
private static final ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
...
ClientResponse clientResponse = resource.type(MediaType.APPLICATION_JSON).get(ClientResponse.class);
InputStream is = clientResponse.getEntityInputStream();
org.springframework.core.env.Environment e = mapper.readValue(is, org.springframework.core.env.Environment.class);
The code above fails with the following error, which makes sense:
com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of org.springframework.core.env.Environment, problem: abstract types either need to be mapped to concrete types, have custom deserializer, or be instantiated with additional type information
But I've tried all the implementations of the Environment class (AbstractEnvironment, MockEnvironment, StandardEnvironment, StandardServletEnvironment) and they all fail as well.
Which class should I use?
org.springframework.core.env.Environment is an interface. So ObjectMapper can not guess what concrete class to instantiate. You need to tell your ObjectMapper which class to use. So in your line
org.springframework.core.env.Environment e = mapper.readValue(is,org.springframework.core.env.Environment.class); You need to replace org.springframework.core.env.Environment.class with some concrete class. For example org.springframework.core.env.StandardEnvironment (depending on what kind of environment actually being returned). Otherwise de-serialize it to map:
Map<String, Object> map = mapper.readValue(is,HashMap<String, Object>.class);
And then go from there
I'm working on aria2 jsonrpc remote revoke, and I found out that all aria2 accept are strings value, like number 1 should be "1".
Although I can use JsonSerializer Annotation or use Module method, I think there should be an easy way which could apply "Int to String Serializer" to all of the fields of type int.
Could anyone give me a hint how to do this?
Finally, I found an article that has described three steps to do that, and I thought that may be a through answer:
Create a custom serializer extending the StdSerializer class
Create an object of SimpleModule class, adding to it the custom serializer and specifying for which class it must be used
Register the module on the ObjectMapper instance
ref: Jackson: create and register a custom JSON serializer with StdSerializer and SimpleModule classes
I have a class in Java that is generically typed. It is supposed to return an object of type T after receiving some json. I am using the following code to create the object:
ObjectMapper mapper = new ObjectMapper();
this.object = mapper.readValue(json, type);
This method throws a JsonMappingException, and should do so if the object isn't of the proper type. The problem I'm running into (when unit testing) is that if I pass in json of an incorrect type, as long as both objects are pojos no exception is being thrown. I am simply getting back an object of the correct type where all it's fields are null.
Why is the exception not getting thrown here? If I pass in some json with a bunch of fields that don't exist on the type of object it should be mapping to, shouldn't I get an exception from that?
You possibly have:
#JsonIgnoreProperties(ignoreUnknown = true)
set somewhere, so jackson doesn't complain about the mismatch.
How do you expect Jackson to know JSON does not represent expected type? JSON data does not have type, beyond just basic Object/Array/scalars structure. So as long as structure is compatible things work, and this is by design.