ByteArrayOutputStream bos = new ByteArrayOutputStream()
ObjectMapper om = objectMapper();
String json = om.writeValueAsString(bos);
public static ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,
ObjectMapper.DefaultTyping.NON_FINAL,
JsonTypeInfo.As.WRAPPER_ARRAY);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
return mapper;
when i write like this code, it goes wrong using jackson 2.13.0, but it works well using jackson 2.12.2
the error info:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class java.io.ByteArrayOutputStream 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:1300) at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:400) at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:46) at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serializeWithType(UnknownSerializer.java:39) at com.fasterxml.jackson.databind.ser.impl.TypeWrappedSerializer.serialize(TypeWrappedSerializer.java:32) at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480) at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319) at com.fasterxml.jackson.databind.ObjectMapper._writeValueAndClose(ObjectMapper.java:4569) at com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(ObjectMapper.java:3822)
I am surprised that one could try to serialize ByteArrayOutputStream
-- that is not supported usage and I don't remember ever adding support (or planning to).
What result would you expect? And what would be the use case?
can't serialize ByteArrayOutputStream object when using jackson 2.13.0
Can't serialize ByteArrayOutputStream
value when using jackson 2.13.0
May 24, 2022
I am surprised that one could try to serialize ByteArrayOutputStream
-- that is not supported usage and I don't remember ever adding support (or planning to).
What result would you expect? And what would be the use case?
ByteArrayOutputStream is used to serialize a photo object , it works well using jackson 2.12.2
@JavaRukawa I don't understand. How could ByteArrayOutputStream
be used that way? What would JSON look like? And how could it be read back?
I could see how one might expect ByteArrayInputStream
(although would disagree due to transient nature of streams) to be useful for serialization. But not output stream.
So. I do not see why or how ByteArrayOutputStream
should be serializable, and Jackson does add any explicit support.
But if you simply want to serialize it as empty Object, you can configure ObjectMapper
like so:
mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
to avoid exception and get {}
as the serialization.
I will close this since I do not see anything to change at this point.
@cowtowncoder FYI this is a regression caused by #3117 where JDK classes could previously be serialized as beans using private fields
previously (confirmed with 2.11) with private visibility enabled it would serialize and deserialize fine, base64 encoding the BAOS.buf
field as:
{"buf":"eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=","count":1}
in 2.13 the visibility config override is ignored for java.*
and javax.*
per this code in MapperConfigBase
:
public final VisibilityChecker<?> getDefaultVisibilityChecker(Class<?> baseType,
AnnotatedClass actualClass)
// 14-Apr-2021, tatu: [databind#3117] JDK types should be limited
// to "public-only" regardless of settings for other types
VisibilityChecker<?> vc;
if (ClassUtil.isJDKClass(baseType)) {
vc = VisibilityChecker.Std.allPublicInstance();
} else {
vc = getDefaultVisibilityChecker();
this means it is no longer possible to serialize JDK classes as beans based on private fields. given that java is becoming stricter about field access, and this was always possibly a bit dodgy, i don't have strong opinions on whether an opt-out for this is worth enabling.
the right thing for OP (and me) is probably custom serialization for BAOS based around BAOS.toByteArray()
.
Thank you @ahgittin -- this makes sense. I will need to update release notes for 2.13 to say something about this.
I'll have to think about it a bit tho... I was about to say that this is completely unsupported behavior, given there is no API for accessing content. Except that, well, there is toByteArray()
.
But maybe it really ought to be supported given it "happened to work" earlier (and I never expected it'd have).
However: I do not think it should produce serialization it used to -- it should, in my opinion, produce simple Base64-encoded value.
I will file a new issue and can consider how to proceed.
One more note: it is still possible to explicitly define Visibility
levels via config overrides, I think so something like:
mapper.configOverride(ByteArrayOutputStream.class)
.setVisibility(JsonAutoDetect.Value.construct(PropertyAccessor.ALL,
JsonAutoDetect.Visibility.ANY));
would allow using the old behavior. Only the default settings have been changed wrt JDK types; it is still possible to override them.
It didn't help
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
objectMapper.configOverride(BufferedInputStream.class).setVisibility(JsonAutoDetect.Value.construct(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY));
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter(objectMapper));
Error:
Type definition error: [simple type, class java.io.BufferedInputStream]
org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class java.io.BufferedInputStream]
at app//org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:489)
at app//org.springframework.http.converter.AbstractGenericHttpMessageConverter.write(AbstractGenericHttpMessageConverter.java:103)
at app//org.springframework.web.client.RestTemplate$HttpEntityRequestCallback.doWithRequest(RestTemplate.java:1077)
at app//org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:860)
at app//org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:714)
@stamanker As comments above and especially, #3493 (comment), this issue is closed and perhaps the new opened issue #3522 can help?
Also, just so you know, we need reports in plain Jackson to work with, meaning we need
ObjectMapper
configuration : how you configured it
Classes to de/serialize
Expected input/output JSON and the actual, and
But "without" Spring
, or other 3rd party frmworks/libs (they usually wrap Jackson with their own stuff)
and so on... whereas your provided stacktrace is in Spring at app//org.springframework....
which is difficult to be helped here.
Thanks!
@cowtowncoder it's the same issue - it was working before.
If anyone has same issue, here is what works:
URL url = new File(filePath).toURI().toURL();
MultiValueMap<String, Object> bodyMap = new LinkedMultiValueMap<>() {{
add("file", new UrlResource(url) {
@Override
public String getFilename() {
return url.getFile();
RequestEntity<?> request = RequestEntity
.post(URI.create(URL))
.headers(new HttpHeaders() {{
// auth header if required
.body(bodyMap);
ResponseEntity<YourDto> result = new RestTemplate().exchange(request, new ParameterizedTypeReference<>() {
@stamanker Ah. Yes, it is similar issue, but not same (from maintainer's POV) as it affects a different JDK class. Change itself may be due to similar underlying change (to prevent handling of JDK types as POJOs for security reasons) or might be something different.
It is possible to report this as breakage to fix if anyone cares about it: if so, that can be discussed in the new issue. From conceptual perspective this type differs so I'd probably not be inclined to support serializability -- even if it happened to be possible earlier (by virtue of default handling considering type just any old POJO).